util/stdmutex.h: Add STDLOCK() and improve annotation checking for StdMutex
What changed, and why it matters
This commit tightens a compile-time safety check in Bitcoin Core's custom mutex wrapper. It adds a macro called STDLOCK() that, when used, asks the compiler to verify the same lock is not being acquired twice in a row by the same thread. It does not change runtime behavior or fix an active exploit; it is a defensive hardening change to catch a specific programming mistake during compilation.
Treat as a low-priority hardening improvement. No urgent action is required. Downstream consumers building with clang thread-safety analysis should prefer STDLOCK() over direct StdLockGuard/StdMutex::Guard usage to benefit from the additional compile-time check, and should plan to remove the deprecated StdLockGuard alias when the TODO is resolved.
Security signals we found
Defensive hardening against double-lock programming errors
Use of clang thread-safety annotations (EXCLUSIVE_LOCKS_REQUIRED, LOCK_RETURNED, SCOPED_LOCKABLE)
Refactoring of lock-guard class without runtime logic change
No evidence of an exploitable vulnerability being patched
Evidence from the diff
The patch refactors StdLockGuard into a nested StdMutex::Guard class and introduces a static inline StdMutex::CheckNotHeld() helper annotated with clang’s Thread Safety Analysis (EXCLUSIVE_LOCKS_REQUIRED(!cs) and LOCK_RETURNED(cs)). A new STDLOCK(cs) macro wraps Guard construction through CheckNotHeld, causing clang to emit a compile-time warning/error if the mutex is already held. A backwards-compatible StdLockGuard alias is retained. The change is purely annotation-driven and does not alter locking semantics at runtime.
Changed components
src/util/stdmutex.hStdMutexStdLockGuard / StdMutex::GuardSTDLOCK macroInspect captured patch +16 / −8
diff --git a/src/util/stdmutex.h b/src/util/stdmutex.h
index 7a3e3039..2cc05013 100644
--- a/src/util/stdmutex.h
+++ b/src/util/stdmutex.h
@@ -10,6 +10,8 @@
// Thread Safety Analysis and provides appropriate annotation macros.
#include <threadsafety.h> // IWYU pragma: export
+#include <util/macros.h>
+
#include <mutex>
// StdMutex provides an annotated version of std::mutex for us,
@@ -23,15 +25,21 @@ public:
//! with the ! operator, to indicate that a mutex should not be held.
const StdMutex& operator!() const { return *this; }
#endif // __clang__
-};
-// StdLockGuard provides an annotated version of std::lock_guard for us,
-// and should only be used when sync.h Mutex/LOCK/etc are not usable.
-class SCOPED_LOCKABLE StdLockGuard : public std::lock_guard<StdMutex>
-{
-public:
- explicit StdLockGuard(StdMutex& cs) EXCLUSIVE_LOCK_FUNCTION(cs) : std::lock_guard<StdMutex>(cs) {}
- ~StdLockGuard() UNLOCK_FUNCTION() = default;
+ // StdMutex::Guard provides an annotated version of std::lock_guard for us.
+ class SCOPED_LOCKABLE Guard : public std::lock_guard<StdMutex>
+ {
+ public:
+ explicit Guard(StdMutex& cs) EXCLUSIVE_LOCK_FUNCTION(cs) : std::lock_guard<StdMutex>(cs) {}
+ ~Guard() UNLOCK_FUNCTION() = default;
+ };
+
+ static inline StdMutex& CheckNotHeld(StdMutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
};
+// Provide STDLOCK(..) wrapper around StdMutex::Guard that checks the lock is not already held
+#define STDLOCK(cs) StdMutex::Guard UNIQUE_NAME(criticalblock){StdMutex::CheckNotHeld(cs)}
+
+using StdLockGuard = StdMutex::Guard; // TODO: remove, provided for backwards compat only
+
#endif // BITCOIN_UTIL_STDMUTEX_H
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.