diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/eval.hh | 2 | ||||
-rw-r--r-- | src/libexpr/parser.y | 18 |
2 files changed, 14 insertions, 6 deletions
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index fa8fa462b..553cbe4fd 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -802,7 +802,7 @@ std::string showType(const Value & v); /** * If `path` refers to a directory, then append "/default.nix". */ -SourcePath resolveExprPath(const SourcePath & path); +SourcePath resolveExprPath(SourcePath path); struct InvalidPathError : EvalError { diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 792f51fde..28f6ba41b 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -682,17 +682,25 @@ Expr * EvalState::parse( } -SourcePath resolveExprPath(const SourcePath & path) +SourcePath resolveExprPath(SourcePath path) { + unsigned int followCount = 0, maxFollow = 1024; + /* If `path' is a symlink, follow it. This is so that relative path references work. */ - auto path2 = path.resolveSymlinks(); + while (true) { + // Basic cycle/depth limit to avoid infinite loops. + if (++followCount >= maxFollow) + throw Error("too many symbolic links encountered while traversing the path '%s'", path); + if (path.lstat().type != InputAccessor::tSymlink) break; + path = {path.accessor, CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))}; + } /* If `path' refers to a directory, append `/default.nix'. */ - if (path2.lstat().type == InputAccessor::tDirectory) - return path2 + "default.nix"; + if (path.lstat().type == InputAccessor::tDirectory) + return path + "default.nix"; - return path2; + return path; } |