Restore old (dis)allowedRequisites behaviour for self-references

stdenv relies on this. So ignore self-references (but only in legacy non-structured attributes mode).
This commit is contained in:
Eelco Dolstra 2018-10-27 15:40:09 +02:00
parent 1427958b3c
commit 18b4c53f71
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 39 additions and 30 deletions

View file

@ -3310,6 +3310,7 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs)
struct Checks
{
bool ignoreSelfRefs = false;
std::experimental::optional<uint64_t> maxSize, maxClosureSize;
std::experimental::optional<Strings> allowedReferences, allowedRequisites, disallowedReferences, disallowedRequisites;
};
@ -3345,35 +3346,6 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs)
return std::make_pair(pathsDone, closureSize);
};
auto checkRefs = [&](const std::experimental::optional<Strings> & value, bool allowed, bool recursive)
{
if (!value) return;
PathSet spec = parseReferenceSpecifiers(worker.store, *drv, *value);
PathSet used = recursive ? getClosure(info.path).first : info.references;
PathSet badPaths;
for (auto & i : used)
if (allowed) {
if (spec.find(i) == spec.end())
badPaths.insert(i);
} else {
if (spec.find(i) != spec.end())
badPaths.insert(i);
}
if (!badPaths.empty()) {
string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n ";
badPathsStr += i;
}
throw BuildError("output '%s' is not allowed to refer to the following paths:%s", info.path, badPathsStr);
}
};
auto applyChecks = [&](const Checks & checks)
{
if (checks.maxSize && info.narSize > *checks.maxSize)
@ -3387,6 +3359,38 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs)
info.path, closureSize, *checks.maxClosureSize);
}
auto checkRefs = [&](const std::experimental::optional<Strings> & value, bool allowed, bool recursive)
{
if (!value) return;
PathSet spec = parseReferenceSpecifiers(worker.store, *drv, *value);
PathSet used = recursive ? getClosure(info.path).first : info.references;
if (recursive && checks.ignoreSelfRefs)
used.erase(info.path);
PathSet badPaths;
for (auto & i : used)
if (allowed) {
if (!spec.count(i))
badPaths.insert(i);
} else {
if (spec.count(i))
badPaths.insert(i);
}
if (!badPaths.empty()) {
string badPathsStr;
for (auto & i : badPaths) {
badPathsStr += "\n ";
badPathsStr += i;
}
throw BuildError("output '%s' is not allowed to refer to the following paths:%s", info.path, badPathsStr);
}
};
checkRefs(checks.allowedReferences, true, false);
checkRefs(checks.allowedRequisites, true, true);
checkRefs(checks.disallowedReferences, false, false);
@ -3435,6 +3439,7 @@ void DerivationGoal::checkOutputs(const std::map<Path, ValidPathInfo> & outputs)
} else {
// legacy non-structured-attributes case
Checks checks;
checks.ignoreSelfRefs = true;
checks.allowedReferences = parsedDrv->getStringsAttr("allowedReferences");
checks.allowedRequisites = parsedDrv->getStringsAttr("allowedRequisites");
checks.disallowedReferences = parsedDrv->getStringsAttr("disallowedReferences");

View file

@ -1,5 +1,7 @@
source common.sh
clearStore
RESULT=$TEST_ROOT/result
dep=$(nix-build -o $RESULT check-refs.nix -A dep)

View file

@ -33,7 +33,7 @@ rec {
};
# When specifying all the requisites, the build succeeds.
test1 = makeTest 1 [ "out" dep1 dep2 deps ];
test1 = makeTest 1 [ dep1 dep2 deps ];
# But missing anything it fails.
test2 = makeTest 2 [ dep2 deps ];

View file

@ -1,5 +1,7 @@
source common.sh
clearStore
RESULT=$TEST_ROOT/result
nix-build -o $RESULT check-reqs.nix -A test1