Fix exception handling around realisePath()

This no longer worked correctly because 'path' is uninitialised when
an exception occurs, leading to errors like

       … while importing ''

       at /nix/store/rrzz5b1pshvzh1437ac9nkl06br81lkv-source/flake.nix:352:13:

So move the adding of the error context into realisePath().
This commit is contained in:
Eelco Dolstra 2022-01-21 13:51:05 +01:00
parent e85cf34ea3
commit 128098040b
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -102,17 +102,30 @@ static Path realisePath(EvalState & state, const Pos & pos, Value & v, const Rea
{ {
PathSet context; PathSet context;
Path path = flags.requireAbsolutePath auto path = [&]()
? state.coerceToPath(pos, v, context) {
: state.coerceToString(pos, v, context, false, false); try {
return flags.requireAbsolutePath
? state.coerceToPath(pos, v, context)
: state.coerceToString(pos, v, context, false, false);
} catch (Error & e) {
e.addTrace(pos, "while realising the context of a path");
throw;
}
}();
StringMap rewrites = state.realiseContext(context); try {
StringMap rewrites = state.realiseContext(context);
auto realPath = state.toRealPath(rewriteStrings(path, rewrites), context); auto realPath = state.toRealPath(rewriteStrings(path, rewrites), context);
return flags.checkForPureEval return flags.checkForPureEval
? state.checkSourcePath(realPath) ? state.checkSourcePath(realPath)
: realPath; : realPath;
} catch (Error & e) {
e.addTrace(pos, "while realising the context of path '%s'", path);
throw;
}
} }
/* Add and attribute to the given attribute map from the output name to /* Add and attribute to the given attribute map from the output name to
@ -150,18 +163,7 @@ static void mkOutputString(
argument. */ argument. */
static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vScope, Value & v) static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vScope, Value & v)
{ {
Path path; auto path = realisePath(state, pos, vPath);
try {
path = realisePath(state, pos, vPath);
} catch (InvalidPathError & e) {
throw EvalError({
.msg = hintfmt("cannot import '%1%', since path '%2%' is not valid", path, e.path),
.errPos = pos
});
} catch (Error & e) {
e.addTrace(pos, "while importing '%s'", path);
throw;
}
// FIXME // FIXME
auto isValidDerivationInStore = [&]() -> std::optional<StorePath> { auto isValidDerivationInStore = [&]() -> std::optional<StorePath> {
@ -314,18 +316,7 @@ extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v);
/* Load a ValueInitializer from a DSO and return whatever it initializes */ /* Load a ValueInitializer from a DSO and return whatever it initializes */
void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v) void prim_importNative(EvalState & state, const Pos & pos, Value * * args, Value & v)
{ {
Path path; auto path = realisePath(state, pos, *args[0]);
try {
path = realisePath(state, pos, *args[0]);
} catch (InvalidPathError & e) {
throw EvalError({
.msg = hintfmt("cannot import '%1%', since path '%2%' is not valid", path, e.path),
.errPos = pos
});
} catch (Error & e) {
e.addTrace(pos, "while importing '%s'", path);
throw;
}
string sym = state.forceStringNoCtx(*args[1], pos); string sym = state.forceStringNoCtx(*args[1], pos);
@ -1379,22 +1370,12 @@ static RegisterPrimOp primop_storePath({
static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args, Value & v)
{ {
Path path; /* We dont check the path right now, because we dont want to
try { throw if the path isnt allowed, but just return false (and we
// We dont check the path right now, because we dont want to throw if cant just catch the exception here because we still want to
// the path isnt allowed, but just return false throw if something in the evaluation of `*args[0]` tries to
// (and we cant just catch the exception here because we still want to access an unauthorized path). */
// throw if something in the evaluation of `*args[0]` tries to access an auto path = realisePath(state, pos, *args[0], { .checkForPureEval = false });
// unauthorized path)
path = realisePath(state, pos, *args[0], { .checkForPureEval = false });
} catch (InvalidPathError & e) {
throw EvalError({
.msg = hintfmt(
"cannot check the existence of '%1%', since path '%2%' is not valid",
path, e.path),
.errPos = pos
});
}
try { try {
v.mkBool(pathExists(state.checkSourcePath(path))); v.mkBool(pathExists(state.checkSourcePath(path)));
@ -1460,15 +1441,7 @@ static RegisterPrimOp primop_dirOf({
/* Return the contents of a file as a string. */ /* Return the contents of a file as a string. */
static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
{ {
Path path; auto path = realisePath(state, pos, *args[0]);
try {
path = realisePath(state, pos, *args[0]);
} catch (InvalidPathError & e) {
throw EvalError({
.msg = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
.errPos = pos
});
}
string s = readFile(path); string s = readFile(path);
if (s.find((char) 0) != string::npos) if (s.find((char) 0) != string::npos)
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path); throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
@ -1512,16 +1485,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
pos pos
); );
Path path; auto path = realisePath(state, pos, *i->value, { .requireAbsolutePath = false });
try {
path = realisePath(state, pos, *i->value, { .requireAbsolutePath = false });
} catch (InvalidPathError & e) {
throw EvalError({
.msg = hintfmt("cannot find '%1%', since path '%2%' is not valid", path, e.path),
.errPos = pos
});
}
searchPath.emplace_back(prefix, path); searchPath.emplace_back(prefix, path);
} }
@ -1548,12 +1512,7 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va
.errPos = pos .errPos = pos
}); });
Path path; auto path = realisePath(state, pos, *args[1]);
try {
path = realisePath(state, pos, *args[1]);
} catch (InvalidPathError & e) {
throw EvalError("cannot read '%s' since path '%s' is not valid, at %s", path, e.path, pos);
}
v.mkString(hashFile(*ht, path).to_string(Base16, false)); v.mkString(hashFile(*ht, path).to_string(Base16, false));
} }
@ -1572,15 +1531,7 @@ static RegisterPrimOp primop_hashFile({
/* Read a directory (without . or ..) */ /* Read a directory (without . or ..) */
static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Value & v)
{ {
Path path; auto path = realisePath(state, pos, *args[0]);
try {
path = realisePath(state, pos, *args[0]);
} catch (InvalidPathError & e) {
throw EvalError({
.msg = hintfmt("cannot read '%1%', since path '%2%' is not valid", path, e.path),
.errPos = pos
});
}
DirEntries entries = readDirectory(path); DirEntries entries = readDirectory(path);