aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2021-12-24 10:02:53 +0100
committerMarcoFalke <falke.marco@gmail.com>2021-12-24 10:02:59 +0100
commitdada92fed2e8a72d91682e7b000703d7723f73b2 (patch)
tree177dadf708b653133976d5c66d52bb39ac20b8bb
parent7551ae81e1a9d5bf14b434bce7528ac000d8afe1 (diff)
parent7b481f015a0386f5ee3e13415474952653ddc198 (diff)
Merge bitcoin/bitcoin#22875: util: Fix Racy ParseOpCode function initialization
7b481f015a0386f5ee3e13415474952653ddc198 Fix Racy ParseOpCode function initialization (Jeremy Rubin) Pull request description: If multiple callers call ParseOpCode concurrently it will cause a race condition. We can either move the static to it's own area and require init be called explicitly, or just allow concurrent first callers to race to fill in an atomic variable that never changes thereafter. The second approach is taken here. Static initialization *is* threadsafe, but only insofar as definining the variable being guaranteed to be called once. This is used incorrectly here. practicalswift --> are there tools we can deploy to catch usage like this? ACKs for top commit: MarcoFalke: re-ACK 7b481f015a0386f5ee3e13415474952653ddc198 🗣 Tree-SHA512: cbf9dc3af26d7335305026f32ce8472a018309b89b3d81a67357e59fbeed72c37b5b8a6e30325ea68145c3b2403867be82de01f22decefb6e6717cf0c0045633
-rw-r--r--src/core_read.cpp26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 484f41f262..1f9227bf0b 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -21,13 +21,15 @@
#include <string>
namespace {
-
-opcodetype ParseOpCode(const std::string& s)
+class OpCodeParser
{
- static std::map<std::string, opcodetype> mapOpNames;
+private:
+ std::map<std::string, opcodetype> mapOpNames;
- if (mapOpNames.empty()) {
- for (unsigned int op = 0; op <= MAX_OPCODE; op++) {
+public:
+ OpCodeParser()
+ {
+ for (unsigned int op = 0; op <= MAX_OPCODE; ++op) {
// Allow OP_RESERVED to get into mapOpNames
if (op < OP_NOP && op != OP_RESERVED) {
continue;
@@ -44,10 +46,18 @@ opcodetype ParseOpCode(const std::string& s)
}
}
}
+ opcodetype Parse(const std::string& s) const
+ {
+ auto it = mapOpNames.find(s);
+ if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode");
+ return it->second;
+ }
+};
- auto it = mapOpNames.find(s);
- if (it == mapOpNames.end()) throw std::runtime_error("script parse error: unknown opcode");
- return it->second;
+opcodetype ParseOpCode(const std::string& s)
+{
+ static const OpCodeParser ocp;
+ return ocp.Parse(s);
}
} // namespace