about summary refs log tree commit diff
path: root/third_party/nix/src/libstore/references.cc
diff options
context:
space:
mode:
authorGriffin Smith <grfn@gws.fyi>2020-08-04T02·13-0400
committerglittershark <grfn@gws.fyi>2020-08-04T22·49+0000
commite634e2757721c420bf52e485019c13bc0b0e0f91 (patch)
tree1dfad214833d0e3d7fb84daab1e799e3477b1f38 /third_party/nix/src/libstore/references.cc
parent94387dbc25e350b56f3ba1c63145ff2ed4c3f43b (diff)
fix(tvix): Partially revert "eliminate exposed global variable" r/1581
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 <mail@tazj.in>
Reviewed-by: kanepyork <rikingcoding@gmail.com>
Diffstat (limited to 'third_party/nix/src/libstore/references.cc')
-rw-r--r--third_party/nix/src/libstore/references.cc54
1 files changed, 36 insertions, 18 deletions
diff --git a/third_party/nix/src/libstore/references.cc b/third_party/nix/src/libstore/references.cc
index 879f126f63ee..b70d282e8df8 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<unsigned char>(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<const char*>(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<const char*>(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<const char*>(data),
+                                     len > refLength ? refLength : len);
+  search(reinterpret_cast<const unsigned char*>(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<const char*>(data) + len - tailLen, tailLen);
 }
 
 PathSet scanForReferences(const std::string& path, const PathSet& refs,