aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Rammhold <andreas@rammhold.de>2021-08-07 19:10:25 +0200
committerAndreas Rammhold <andreas@rammhold.de>2021-08-07 19:10:25 +0200
commitb2d3976163ef4feaa9881f9dd001ec886f34cde9 (patch)
treee778428ad0de36a9fa98a67f35fdd89c997bbc19 /src
parent2b67cb7b8c8ac7953f7e341d760bdb3c021fe765 (diff)
Fix potential race-condition in reference scanning code
Previously the code ensures that the isBase32 array would only be initialised once in a single-threaded context. If two threads happen to call the function before the initialisation was completed both of them would have completed the initialization step. This allowed for a race-condition where one thread might be done with the initialization but the other thread sets all the fields to false again. For a brief moment the base32 detection would then produce false-negatives.
Diffstat (limited to 'src')
-rw-r--r--src/libstore/references.cc8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/libstore/references.cc b/src/libstore/references.cc
index 39c4970c6..3a07c1411 100644
--- a/src/libstore/references.cc
+++ b/src/libstore/references.cc
@@ -5,6 +5,7 @@
#include <map>
#include <cstdlib>
+#include <mutex>
namespace nix {
@@ -16,14 +17,13 @@ static unsigned int refLength = 32; /* characters */
static void search(const unsigned char * s, size_t len,
StringSet & hashes, StringSet & seen)
{
- static bool initialised = false;
+ static std::once_flag initialised;
static bool isBase32[256];
- if (!initialised) {
+ std::call_once(initialised, [](){
for (unsigned int i = 0; i < 256; ++i) isBase32[i] = false;
for (unsigned int i = 0; i < base32Chars.size(); ++i)
isBase32[(unsigned char) base32Chars[i]] = true;
- initialised = true;
- }
+ });
for (size_t i = 0; i + refLength <= len; ) {
int j;