From d2e6cfa0750cb38ceef7dc0b8bb31cf3b0387e9c Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 25 Aug 2023 17:17:33 +0200 Subject: [PATCH 1/2] tests/lang/eval-okay-pathexists: Add cases --- tests/lang/eval-okay-pathexists.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/lang/eval-okay-pathexists.nix b/tests/lang/eval-okay-pathexists.nix index 50c28ee0c..8eae37e70 100644 --- a/tests/lang/eval-okay-pathexists.nix +++ b/tests/lang/eval-okay-pathexists.nix @@ -1,4 +1,6 @@ -builtins.pathExists (builtins.toPath ./lib.nix) +builtins.pathExists (./lib.nix) +&& builtins.pathExists (builtins.toPath ./lib.nix) +&& builtins.pathExists (builtins.toString ./lib.nix) && builtins.pathExists (builtins.toPath (builtins.toString ./lib.nix)) && !builtins.pathExists (builtins.toPath (builtins.toString ./bla.nix)) && builtins.pathExists ./lib.nix From 1e08e12d8138b09e6872cb498b723ade9ad71d68 Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Fri, 25 Aug 2023 17:18:37 +0200 Subject: [PATCH 2/2] pathExists: isDir when endswith / Fixes https://github.com/NixOS/nix/issues/8838 --- src/libexpr/primops.cc | 16 +++++++++++++--- tests/lang/eval-okay-pathexists.nix | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 283f99a48..915b872c8 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1520,15 +1520,25 @@ static RegisterPrimOp primop_storePath({ static void prim_pathExists(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + auto & arg = *args[0]; + /* We don’t check the path right now, because we don’t want to throw if the path isn’t allowed, but just return false (and we can’t just catch the exception here because we still want to - throw if something in the evaluation of `*args[0]` tries to + throw if something in the evaluation of `arg` tries to access an unauthorized path). */ - auto path = realisePath(state, pos, *args[0], { .checkForPureEval = false }); + auto path = realisePath(state, pos, arg, { .checkForPureEval = false }); + + /* SourcePath doesn't know about trailing slash. */ + auto mustBeDir = arg.type() == nString && arg.str().ends_with("/"); try { - v.mkBool(state.checkSourcePath(path).pathExists()); + auto checked = state.checkSourcePath(path); + auto exists = checked.pathExists(); + if (exists && mustBeDir) { + exists = checked.lstat().type == InputAccessor::tDirectory; + } + v.mkBool(exists); } catch (SysError & e) { /* Don't give away info from errors while canonicalising ‘path’ in restricted mode. */ diff --git a/tests/lang/eval-okay-pathexists.nix b/tests/lang/eval-okay-pathexists.nix index 8eae37e70..e1246e370 100644 --- a/tests/lang/eval-okay-pathexists.nix +++ b/tests/lang/eval-okay-pathexists.nix @@ -1,6 +1,7 @@ builtins.pathExists (./lib.nix) && builtins.pathExists (builtins.toPath ./lib.nix) && builtins.pathExists (builtins.toString ./lib.nix) +&& !builtins.pathExists (builtins.toString ./lib.nix + "/") && builtins.pathExists (builtins.toPath (builtins.toString ./lib.nix)) && !builtins.pathExists (builtins.toPath (builtins.toString ./bla.nix)) && builtins.pathExists ./lib.nix