1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-27 12:41:00 +01:00

Add a special type of context for the result of toString

When you apply `builtins.toString` to a path value representing a path
in the Nix store (as is the case with flake inputs), historically you
got a string without context (e.g. `/nix/store/...-source`). This is
broken, since it allows you to pass a store path to a
derivation/toFile without a proper store reference. This is especially
a problem with lazy trees, since the store path is a virtual path that
doesn't exist and can be different every time.

For backwards compatibility, and to warn users about this unsafe use
of `toString`, we now keep track of such strings as a special type of
context.
This commit is contained in:
Eelco Dolstra 2025-05-07 18:53:39 +02:00
parent 8c568277fd
commit 2a35d8f800
10 changed files with 129 additions and 10 deletions

View file

@ -89,6 +89,9 @@ StringMap EvalState::realiseContext(const NixStringContext & context, StorePathS
if (maybePathsOut)
maybePathsOut->emplace(d.drvPath);
},
[&](const NixStringContextElem::Path & p) {
// FIXME
},
}, c.raw);
}
@ -1438,6 +1441,9 @@ static void derivationStrictInternal(
[&](const NixStringContextElem::Opaque & o) {
drv.inputSrcs.insert(state.devirtualize(o.path, &rewrites));
},
[&](const NixStringContextElem::Path & p) {
// FIXME: do something
},
}, c.raw);
}
@ -2346,10 +2352,21 @@ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Val
std::string contents(state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.toFile"));
StorePathSet refs;
StringMap rewrites;
for (auto c : context) {
if (auto p = std::get_if<NixStringContextElem::Opaque>(&c.raw))
refs.insert(p->path);
else if (auto p = std::get_if<NixStringContextElem::Path>(&c.raw)) {
if (contents.find(p->storePath.to_string()) != contents.npos) {
warn(
"Using 'builtins.toFile' to create a file named '%s' that references the store path '%s' without a proper context. "
"The resulting file will not have a correct store reference, so this is unreliable and may stop working in the future.",
name,
state.store->printStorePath(p->storePath));
state.devirtualize(p->storePath, &rewrites);
}
}
else
state.error<EvalError>(
"files created by %1% may not reference derivations, but %2% references %3%",
@ -2359,6 +2376,8 @@ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Val
).atPos(pos).debugThrow();
}
contents = rewriteStrings(contents, rewrites);
auto storePath = settings.readOnlyMode
? state.store->makeFixedOutputPathFromCA(name, TextInfo {
.hash = hashString(HashAlgorithm::SHA256, contents),