diff --git a/zeroize/CHANGELOG.md b/zeroize/CHANGELOG.md index 0272a4c9..51e3b421 100644 --- a/zeroize/CHANGELOG.md +++ b/zeroize/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.9.1 (UNRELEASED) +### Fixed +- False positive failures in proxy allocator test ([#1538]) + +[#1538]: https://github.com/RustCrypto/utils/pull/1538 + ## 1.9.0 (2026-06-12) ### Added - `Zeroizing` is now `repr(transparent)` ([#1253]) diff --git a/zeroize/tests/alloc.rs b/zeroize/tests/alloc.rs index 5dbdd715..9a575d7d 100644 --- a/zeroize/tests/alloc.rs +++ b/zeroize/tests/alloc.rs @@ -1,24 +1,32 @@ //! Tests for `Zeroize` impls on heap-allocated data structures -#![allow(clippy::std_instead_of_core, clippy::undocumented_unsafe_blocks)] - -use std::alloc::{GlobalAlloc, Layout, System}; +use core::{ + alloc::{GlobalAlloc, Layout}, + ptr, + sync::atomic::{AtomicPtr, Ordering::Relaxed}, +}; use zeroize::Zeroize; -// Allocator that ensures that deallocated data is zeroized. +use std::alloc::System; + +static REG_PTR: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + +// Allocator that ensures that allocation registered in `REG_PTR` is zeroized. struct ProxyAllocator; +#[allow(clippy::undocumented_unsafe_blocks)] unsafe impl GlobalAlloc for ProxyAllocator { unsafe fn alloc(&self, layout: Layout) -> *mut u8 { unsafe { System.alloc(layout) } } unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - if layout.size() == 160 { + if ptr == REG_PTR.load(Relaxed) { for i in 0..layout.size() { - let b = unsafe { core::ptr::read(ptr.add(i)) }; + let b = unsafe { ptr::read(ptr.add(i)) }; assert_eq!(b, 0); } + REG_PTR.store(ptr::null_mut(), Relaxed); } unsafe { System.dealloc(ptr, layout) } @@ -32,7 +40,11 @@ struct SecretBox(Box); impl SecretBox { fn new(val: S) -> Self { - Self(Box::new(val)) + let mut b = Box::new(val); + // TODO(MSRV-1.98): use `Box::as_mut_ptr` + let p: *mut S = &raw mut *b; + REG_PTR.store(p.cast(), Relaxed); + Self(b) } } @@ -42,19 +54,15 @@ impl Drop for SecretBox { } } -#[test] -fn secret_box_alloc_test() { - let b1 = SecretBox::new([u128::MAX; 10]); - core::hint::black_box(&b1); - let b2 = SecretBox::new([u8::MAX; 160]); - core::hint::black_box(&b2); -} - struct ObserveSecretBox(Box); impl ObserveSecretBox { fn new(val: S) -> Self { - Self(Box::new(val)) + let mut b = Box::new(val); + // TODO(MSRV-1.98): use `Box::as_mut_ptr` + let p: *mut S = &raw mut *b; + REG_PTR.store(p.cast(), Relaxed); + Self(b) } } @@ -66,9 +74,20 @@ impl Drop for ObserveSecretBox { } #[test] -fn observe_secret_box_alloc_test() { - let b1 = ObserveSecretBox::new([u128::MAX; 10]); +fn proxy_alloc_test() { + let b1 = SecretBox::new([u128::MAX; 10]); core::hint::black_box(&b1); + drop(b1); + let b2 = SecretBox::new([u8::MAX; 160]); core::hint::black_box(&b2); + drop(b2); + + let b3 = ObserveSecretBox::new([u128::MAX; 10]); + core::hint::black_box(&b3); + drop(b3); + + let b4 = SecretBox::new([u8::MAX; 160]); + core::hint::black_box(&b4); + drop(b4); }