From bef68e53b9d08c99873a5bc60568b7351934ad51 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 16 Nov 2023 16:45:14 +0100 Subject: [PATCH] Fix symlink handling This restores the symlink handling behaviour prior to 94812cca98fbb157e5f64a15a85a2b852d289feb. Fixes #9298. (cherry picked from commit 31ebc6028b3682969d86a7b39ae87131c41cc604) --- src/libexpr/eval.hh | 2 +- src/libexpr/parser.y | 18 +++++++++++++----- .../lang/eval-okay-symlink-resolution.exp | 1 + .../lang/eval-okay-symlink-resolution.nix | 1 + .../symlink-resolution/foo/lib/default.nix | 1 + .../lang/symlink-resolution/foo/overlays | 1 + .../symlink-resolution/overlays/overlay.nix | 1 + 7 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tests/functional/lang/eval-okay-symlink-resolution.exp create mode 100644 tests/functional/lang/eval-okay-symlink-resolution.nix create mode 100644 tests/functional/lang/symlink-resolution/foo/lib/default.nix create mode 120000 tests/functional/lang/symlink-resolution/foo/overlays create mode 100644 tests/functional/lang/symlink-resolution/overlays/overlay.nix 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; } diff --git a/tests/functional/lang/eval-okay-symlink-resolution.exp b/tests/functional/lang/eval-okay-symlink-resolution.exp new file mode 100644 index 000000000..8b8441b91 --- /dev/null +++ b/tests/functional/lang/eval-okay-symlink-resolution.exp @@ -0,0 +1 @@ +"test" diff --git a/tests/functional/lang/eval-okay-symlink-resolution.nix b/tests/functional/lang/eval-okay-symlink-resolution.nix new file mode 100644 index 000000000..ffb1818bd --- /dev/null +++ b/tests/functional/lang/eval-okay-symlink-resolution.nix @@ -0,0 +1 @@ +import symlink-resolution/foo/overlays/overlay.nix diff --git a/tests/functional/lang/symlink-resolution/foo/lib/default.nix b/tests/functional/lang/symlink-resolution/foo/lib/default.nix new file mode 100644 index 000000000..8b8441b91 --- /dev/null +++ b/tests/functional/lang/symlink-resolution/foo/lib/default.nix @@ -0,0 +1 @@ +"test" diff --git a/tests/functional/lang/symlink-resolution/foo/overlays b/tests/functional/lang/symlink-resolution/foo/overlays new file mode 120000 index 000000000..0d44a21c5 --- /dev/null +++ b/tests/functional/lang/symlink-resolution/foo/overlays @@ -0,0 +1 @@ +../overlays \ No newline at end of file diff --git a/tests/functional/lang/symlink-resolution/overlays/overlay.nix b/tests/functional/lang/symlink-resolution/overlays/overlay.nix new file mode 100644 index 000000000..b0368308e --- /dev/null +++ b/tests/functional/lang/symlink-resolution/overlays/overlay.nix @@ -0,0 +1 @@ +import ../lib