1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-06 21:41:48 +02:00

GitArchiveInputScheme: Verify the locked tree hash

This commit is contained in:
Eelco Dolstra 2023-02-03 15:31:36 +01:00
parent ca26ce994b
commit 219510b6ab
3 changed files with 36 additions and 19 deletions

View file

@ -132,24 +132,24 @@ std::pair<StorePath, Input> Input::fetchToStore(ref<Store> store) const
return {std::move(storePath), input};
}
void Input::checkLocks(Input & input) const
void InputScheme::checkLocks(const Input & specified, const Input & final) const
{
if (auto prevNarHash = getNarHash()) {
if (input.getNarHash() != prevNarHash)
if (auto prevNarHash = specified.getNarHash()) {
if (final.getNarHash() != prevNarHash)
throw Error((unsigned int) 102, "NAR hash mismatch in input '%s', expected '%s'",
to_string(), prevNarHash->to_string(SRI, true));
specified.to_string(), prevNarHash->to_string(SRI, true));
}
if (auto prevLastModified = getLastModified()) {
if (input.getLastModified() != prevLastModified)
if (auto prevLastModified = specified.getLastModified()) {
if (final.getLastModified() != prevLastModified)
throw Error("'lastModified' attribute mismatch in input '%s', expected %d",
input.to_string(), *prevLastModified);
final.to_string(), *prevLastModified);
}
if (auto prevRevCount = getRevCount()) {
if (input.getRevCount() != prevRevCount)
if (auto prevRevCount = specified.getRevCount()) {
if (final.getRevCount() != prevRevCount)
throw Error("'revCount' attribute mismatch in input '%s', expected %d",
input.to_string(), *prevRevCount);
final.to_string(), *prevRevCount);
}
}
@ -163,7 +163,7 @@ std::pair<ref<InputAccessor>, Input> Input::getAccessor(ref<Store> store) const
try {
auto [accessor, final] = scheme->getAccessor(store, *this);
accessor->fingerprint = scheme->getFingerprint(store, final);
checkLocks(final);
scheme->checkLocks(*this, final);
return {accessor, std::move(final)};
} catch (Error & e) {
e.addTrace({}, "while fetching the input '%s'", to_string());

View file

@ -92,10 +92,6 @@ public:
// For locked inputs, returns a string that uniquely specifies the
// content of the input (typically a commit hash or content hash).
std::optional<std::string> getFingerprint(ref<Store> store) const;
private:
void checkLocks(Input & input) const;
};
/* The InputScheme represents a type of fetcher. Each fetcher
@ -142,6 +138,8 @@ struct InputScheme
{ return std::nullopt; }
virtual std::optional<std::string> getFingerprint(ref<Store> store, const Input & input) const;
virtual void checkLocks(const Input & specified, const Input & final) const;
};
void registerInputScheme(std::shared_ptr<InputScheme> && fetcher);

View file

@ -107,8 +107,11 @@ struct GitArchiveInputScheme : InputScheme
{
if (maybeGetStrAttr(attrs, "type") != type()) return {};
static std::unordered_set<std::string> known =
{"type", "owner", "repo", "ref", "rev", "narHash", "lastModified", "host", "treeHash"};
for (auto & [name, value] : attrs)
if (name != "type" && name != "owner" && name != "repo" && name != "ref" && name != "rev" && name != "narHash" && name != "lastModified" && name != "host")
if (!known.contains(name))
throw Error("unsupported input attribute '%s'", name);
getStrAttr(attrs, "owner");
@ -155,6 +158,23 @@ struct GitArchiveInputScheme : InputScheme
return input;
}
std::optional<Hash> getTreeHash(const Input & input) const
{
if (auto treeHash = maybeGetStrAttr(input.attrs, "treeHash"))
return Hash::parseAny(*treeHash, htSHA1);
else
return std::nullopt;
}
void checkLocks(const Input & specified, const Input & final) const override
{
if (auto prevTreeHash = getTreeHash(specified)) {
if (getTreeHash(final) != prevTreeHash)
throw Error("Git tree hash mismatch in input '%s', expected '%s'",
specified.to_string(), prevTreeHash->gitRev());
}
}
std::optional<std::string> getAccessToken(const std::string & host) const
{
auto tokens = fetchSettings.accessTokens.get();
@ -214,9 +234,6 @@ struct GitArchiveInputScheme : InputScheme
auto treeHash = importTarball(*source);
// FIXME: verify against locked tree hash.
input.attrs.insert_or_assign("treeHash", treeHash.gitRev());
cache->upsertFact(treeHashKey, treeHash.gitRev());
return {std::move(input), treeHash};
@ -226,6 +243,8 @@ struct GitArchiveInputScheme : InputScheme
{
auto [input, treeHash] = downloadArchive(store, _input);
input.attrs.insert_or_assign("treeHash", treeHash.gitRev());
auto accessor = makeTarballCacheAccessor(treeHash);
#if 0