diff options
author | Andreas Rammhold <andreas@rammhold.de> | 2021-08-07 19:10:25 +0200 |
---|---|---|
committer | Andreas Rammhold <andreas@rammhold.de> | 2021-08-07 19:10:25 +0200 |
commit | b2d3976163ef4feaa9881f9dd001ec886f34cde9 (patch) | |
tree | e778428ad0de36a9fa98a67f35fdd89c997bbc19 | |
parent | 2b67cb7b8c8ac7953f7e341d760bdb3c021fe765 (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.
-rw-r--r-- | src/libstore/references.cc | 8 |
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; |