diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 3a27527a0..eb3116d81 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -719,7 +719,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * throw Error(format("multiple outputs are not supported in fixed-output derivations, at %1%") % posDrvName); HashType ht = outputHashAlgo.empty() ? htUnknown : parseHashType(outputHashAlgo); - Hash h(*outputHash, ht); + + Hash h = newHashAllowEmpty(*outputHash, ht); auto outPath = state.store->makeFixedOutputPath(ingestionMethod, h, drvName); if (!jsonObject) drv.env["out"] = state.store->printStorePath(outPath); @@ -1126,7 +1127,7 @@ static void prim_path(EvalState & state, const Pos & pos, Value * * args, Value } else if (n == "recursive") method = FileIngestionMethod { state.forceBool(*attr.value, *attr.pos) }; else if (n == "sha256") - expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); + expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); else throw EvalError(format("unsupported argument '%1%' to 'addPath', at %2%") % attr.name % *attr.pos); } diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc index b90408798..97254aa04 100644 --- a/src/libexpr/primops/fetchTree.cc +++ b/src/libexpr/primops/fetchTree.cc @@ -103,7 +103,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v, if (n == "url") url = state.forceStringNoCtx(*attr.value, *attr.pos); else if (n == "sha256") - expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); + expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256); else if (n == "name") name = state.forceStringNoCtx(*attr.value, *attr.pos); else diff --git a/src/libfetchers/fetchers.cc b/src/libfetchers/fetchers.cc index ca555114d..11cac4c55 100644 --- a/src/libfetchers/fetchers.cc +++ b/src/libfetchers/fetchers.cc @@ -36,7 +36,7 @@ std::unique_ptr inputFromAttrs(const Attrs & attrs) if (res) { if (auto narHash = maybeGetStrAttr(attrs, "narHash")) // FIXME: require SRI hash. - res->narHash = Hash(*narHash); + res->narHash = newHashAllowEmpty(*narHash, htUnknown); return res; } } diff --git a/src/libfetchers/tarball.cc b/src/libfetchers/tarball.cc index 1b0eba18a..7966da314 100644 --- a/src/libfetchers/tarball.cc +++ b/src/libfetchers/tarball.cc @@ -264,8 +264,7 @@ struct TarballInputScheme : InputScheme auto input = std::make_unique(parseURL(getStrAttr(attrs, "url"))); if (auto hash = maybeGetStrAttr(attrs, "hash")) - // FIXME: require SRI hash. - input->hash = Hash(*hash); + input->hash = newHashAllowEmpty(*hash, htUnknown); return input; } diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 7caee1da7..3f6d4c0c9 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -205,6 +205,16 @@ Hash::Hash(const std::string & s, HashType type) throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(type)); } +Hash newHashAllowEmpty(std::string hashStr, HashType ht) +{ + if (hashStr.empty()) + { + Hash h(ht); + warn("found empty hash, assuming you wanted '%s'", h.to_string(SRI)); + } else + return Hash(hashStr, ht); +} + union Ctx { diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index 4ff13f6b2..5080539b2 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -94,6 +94,8 @@ struct Hash } }; +/* Helper that defaults empty hashes to the 0 hash. */ +Hash newHashAllowEmpty(std::string hashStr, HashType ht); /* Print a hash in base-16 if it's MD5, or base-32 otherwise. */ string printHash16or32(const Hash & hash);