From e634e2757721c420bf52e485019c13bc0b0e0f91 Mon Sep 17 00:00:00 2001 From: Griffin Smith Date: Mon, 3 Aug 2020 22:13:40 -0400 Subject: fix(tvix): Partially revert "eliminate exposed global variable" This reverts part of commit 976a36c2e482f416acd79a624e6d96cce2564b5b, which was causing scanForReferences to hang indefinitely. I'm not sure what the original intent of the commit was since there's not really much of a commit message on it, but with this I am able to fully realise derivations. Change-Id: I620e892e2fe2244f066512286b086b3dd8f8f6c0 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1635 Tested-by: BuildkiteCI Reviewed-by: tazjin Reviewed-by: kanepyork --- third_party/nix/src/libstore/references.cc | 54 ++++++++++++++++++++---------- third_party/nix/src/libutil/hash.cc | 3 -- third_party/nix/src/libutil/hash.hh | 3 ++ 3 files changed, 39 insertions(+), 21 deletions(-) (limited to 'third_party') diff --git a/third_party/nix/src/libstore/references.cc b/third_party/nix/src/libstore/references.cc index 879f126f63..b70d282e8d 100644 --- a/third_party/nix/src/libstore/references.cc +++ b/third_party/nix/src/libstore/references.cc @@ -13,21 +13,38 @@ namespace nix { static unsigned int refLength = 32; /* characters */ -static void search(const char* s, size_t len, StringSet& hashes, +static void search(const unsigned char* s, size_t len, StringSet& hashes, StringSet& seen) { + static bool initialised = false; + static bool isBase32[256]; + if (!initialised) { + for (bool& i : isBase32) { + i = false; + } + for (char base32Char : base32Chars) { + isBase32[static_cast(base32Char)] = true; + } + initialised = true; + } + for (size_t i = 0; i + refLength <= len;) { - absl::string_view ref(s + i, refLength); - bool match = Hash::IsValidBase32(ref); + int j = 0; + bool match = true; + for (j = refLength - 1; j >= 0; --j) { + if (!isBase32[s[i + j]]) { + i += j + 1; + match = false; + break; + } + } if (!match) { continue; } - // TODO(kanepyork): convert StringSet to flat_hash_set, delay owned string - // conversion into the 'if' - std::string sref(ref); - if (hashes.find(sref) != hashes.end()) { + std::string ref(reinterpret_cast(s) + i, refLength); + if (hashes.find(ref) != hashes.end()) { DLOG(INFO) << "found reference to '" << ref << "' at offset " << i; - seen.insert(sref); - hashes.erase(sref); + seen.insert(ref); + hashes.erase(ref); } ++i; } @@ -48,21 +65,22 @@ struct RefScanSink : Sink { void RefScanSink::operator()(const unsigned char* data, size_t len) { hashSink(data, len); - const char* data_ = reinterpret_cast(data); - /* It's possible that a reference spans the previous and current fragment, so search in the concatenation of the tail of the previous fragment and the start of the current fragment. */ - std::string s = tail + std::string(data_, len > refLength ? refLength : len); - search(s.data(), s.size(), hashes, seen); + std::string s = tail + std::string(reinterpret_cast(data), + len > refLength ? refLength : len); + search(reinterpret_cast(s.data()), s.size(), hashes, + seen); - search(data_, len, hashes, seen); + search(data, len, hashes, seen); size_t tailLen = len <= refLength ? len : refLength; - tail = std::string(tail, tail.size() < refLength - tailLen - ? 0 - : tail.size() - (refLength - tailLen)) + - std::string(data_ + len - tailLen, tailLen); + tail = + std::string(tail, tail.size() < refLength - tailLen + ? 0 + : tail.size() - (refLength - tailLen)) + + std::string(reinterpret_cast(data) + len - tailLen, tailLen); } PathSet scanForReferences(const std::string& path, const PathSet& refs, diff --git a/third_party/nix/src/libutil/hash.cc b/third_party/nix/src/libutil/hash.cc index ac151201fd..97cc137b11 100644 --- a/third_party/nix/src/libutil/hash.cc +++ b/third_party/nix/src/libutil/hash.cc @@ -104,9 +104,6 @@ bool Hash::IsValidBase16(absl::string_view s) { return true; } -// omitted: E O U T -constexpr char base32Chars[] = "0123456789abcdfghijklmnpqrsvwxyz"; - constexpr signed char kUnBase32[] = { -1, -1, -1, -1, -1, -1, -1, -1, /* unprintables */ -1, -1, -1, -1, -1, -1, -1, -1, /* unprintables */ diff --git a/third_party/nix/src/libutil/hash.hh b/third_party/nix/src/libutil/hash.hh index 56845e7154..bc32f91463 100644 --- a/third_party/nix/src/libutil/hash.hh +++ b/third_party/nix/src/libutil/hash.hh @@ -21,6 +21,9 @@ const int sha1HashSize = 20; const int sha256HashSize = 32; const int sha512HashSize = 64; +// omitted: E O U T +constexpr char base32Chars[] = "0123456789abcdfghijklmnpqrsvwxyz"; + enum Base : int { Base64, Base32, Base16, SRI }; struct Hash { -- cgit 1.4.1