diff options
Diffstat (limited to 'src/libutil/hash.cc')
-rw-r--r-- | src/libutil/hash.cc | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/src/libutil/hash.cc b/src/libutil/hash.cc index 460d479a3..c8fcdfed0 100644 --- a/src/libutil/hash.cc +++ b/src/libutil/hash.cc @@ -4,6 +4,7 @@ #include <openssl/md5.h> #include <openssl/sha.h> +#include "args.hh" #include "hash.hh" #include "archive.hh" #include "util.hh" @@ -18,11 +19,13 @@ namespace nix { void Hash::init() { - if (type == htMD5) hashSize = md5HashSize; - else if (type == htSHA1) hashSize = sha1HashSize; - else if (type == htSHA256) hashSize = sha256HashSize; - else if (type == htSHA512) hashSize = sha512HashSize; - else abort(); + if (!type) abort(); + switch (*type) { + case htMD5: hashSize = md5HashSize; break; + case htSHA1: hashSize = sha1HashSize; break; + case htSHA256: hashSize = sha256HashSize; break; + case htSHA512: hashSize = sha512HashSize; break; + } assert(hashSize <= maxHashSize); memset(hash, 0, maxHashSize); } @@ -102,11 +105,18 @@ string printHash16or32(const Hash & hash) } +HashType assertInitHashType(const Hash & h) { + if (h.type) + return *h.type; + else + abort(); +} + std::string Hash::to_string(Base base, bool includeType) const { std::string s; if (base == SRI || includeType) { - s += printHashType(type); + s += printHashType(assertInitHashType(*this)); s += base == SRI ? '-' : ':'; } switch (base) { @@ -124,8 +134,10 @@ std::string Hash::to_string(Base base, bool includeType) const return s; } +Hash::Hash(std::string_view s, HashType type) : Hash(s, std::optional { type }) { } +Hash::Hash(std::string_view s) : Hash(s, std::optional<HashType>{}) { } -Hash::Hash(std::string_view s, HashType type) +Hash::Hash(std::string_view s, std::optional<HashType> type) : type(type) { size_t pos = 0; @@ -136,17 +148,17 @@ Hash::Hash(std::string_view s, HashType type) sep = s.find('-'); if (sep != string::npos) { isSRI = true; - } else if (type == htUnknown) + } else if (! type) throw BadHash("hash '%s' does not include a type", s); } if (sep != string::npos) { string hts = string(s, 0, sep); this->type = parseHashType(hts); - if (this->type == htUnknown) + if (!this->type) throw BadHash("unknown hash type '%s'", hts); - if (type != htUnknown && type != this->type) - throw BadHash("hash '%s' should have type '%s'", s, printHashType(type)); + if (type && type != this->type) + throw BadHash("hash '%s' should have type '%s'", s, printHashType(*type)); pos = sep + 1; } @@ -202,13 +214,15 @@ Hash::Hash(std::string_view s, HashType type) } else - throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(type)); + throw BadHash("hash '%s' has wrong length for hash type '%s'", s, printHashType(*type)); } -Hash newHashAllowEmpty(std::string hashStr, HashType ht) +Hash newHashAllowEmpty(std::string hashStr, std::optional<HashType> ht) { if (hashStr.empty()) { - Hash h(ht); + if (!ht) + throw BadHash("empty hash requires explicit hash type"); + Hash h(*ht); warn("found empty hash, assuming '%s'", h.to_string(SRI, true)); return h; } else @@ -328,24 +342,35 @@ Hash compressHash(const Hash & hash, unsigned int newSize) } -HashType parseHashType(const string & s) +std::optional<HashType> parseHashTypeOpt(const string & s) { if (s == "md5") return htMD5; else if (s == "sha1") return htSHA1; else if (s == "sha256") return htSHA256; else if (s == "sha512") return htSHA512; - else return htUnknown; + else return std::optional<HashType> {}; } +HashType parseHashType(const string & s) +{ + auto opt_h = parseHashTypeOpt(s); + if (opt_h) + return *opt_h; + else + throw UsageError("unknown hash algorithm '%1%'", s); +} string printHashType(HashType ht) { - if (ht == htMD5) return "md5"; - else if (ht == htSHA1) return "sha1"; - else if (ht == htSHA256) return "sha256"; - else if (ht == htSHA512) return "sha512"; - else abort(); + switch (ht) { + case htMD5: return "md5"; break; + case htSHA1: return "sha1"; break; + case htSHA256: return "sha256"; break; + case htSHA512: return "sha512"; break; + } + // illegal hash type enum value internally, as opposed to external input + // which should be validated with nice error message. + abort(); } - } |