diff --git a/polkadot/node/tracking-allocator/src/lib.rs b/polkadot/node/tracking-allocator/src/lib.rs index 8441bd1ffafa..ab8597b5c382 100644 --- a/polkadot/node/tracking-allocator/src/lib.rs +++ b/polkadot/node/tracking-allocator/src/lib.rs @@ -72,8 +72,11 @@ impl Spinlock { } } + // SAFETY: It should be only called from the guard's destructor. Calling it explicitly while + // the guard is alive is undefined behavior, as it breaks the security contract of `Deref` and + // `DerefMut`, which implies that lock is held at the moment of dereferencing. #[inline] - fn unlock(&self) { + unsafe fn unlock(&self) { self.lock.store(false, Ordering::Release); } } @@ -97,7 +100,9 @@ impl DerefMut for SpinlockGuard<'_, T> { impl Drop for SpinlockGuard<'_, T> { fn drop(&mut self) { - self.lock.unlock(); + // SAFETY: Calling `unlock` is only safe when it's guaranteed no guard outlives the + // unlocking point; here, the guard is dropped, so it is safe. + unsafe { self.lock.unlock() } } }