diff --git a/src/libfetchers/input-accessor.cc b/src/libfetchers/input-accessor.cc index fb26ced4b..7e4c46cff 100644 --- a/src/libfetchers/input-accessor.cc +++ b/src/libfetchers/input-accessor.cc @@ -289,10 +289,14 @@ SourcePath SourcePath::resolveSymlinks() const { CanonPath res("/"); + int linksAllowed = 1024; + for (auto & component : path) { res.push(component); while (true) { if (auto st = accessor.maybeLstat(res)) { + if (!linksAllowed--) + throw Error("infinite symlink recursion in path '%s'", path); if (st->type != InputAccessor::tSymlink) break; auto target = accessor.readLink(res); if (hasPrefix(target, "/")) diff --git a/tests/eval.sh b/tests/eval.sh index d74976019..ffae08a6a 100644 --- a/tests/eval.sh +++ b/tests/eval.sh @@ -29,3 +29,7 @@ nix-instantiate --eval -E 'assert 1 + 2 == 3; true' [[ $(nix-instantiate -A attr --eval "./eval.nix") == '{ foo = "bar"; }' ]] [[ $(nix-instantiate -A attr --eval --json "./eval.nix") == '{"foo":"bar"}' ]] [[ $(nix-instantiate -A int --eval - < "./eval.nix") == 123 ]] + +# Check that symlink cycles don't cause a hang. +ln -sfn cycle.nix $TEST_ROOT/cycle.nix +(! nix eval --file $TEST_ROOT/cycle.nix)