RUSTSEC-2026-0143
Double-free in `vmem` storage reachable from safe Rust
Details
When the `vmem` feature is enabled, `VmemStorage<T>::new(Box<[UnsafeSyncCell<T>]>)` (and every public constructor that funnels through it — `ConcurrentHeapRB::default(cap)`, `ConcurrentHeapRB::from(Vec<T>)`, `From<Box<[T]>>`, etc.) bit-copies the input buffer into a freshly `mmap`'d region with `ptr::copy_nonoverlapping`, then lets the source `Box<[UnsafeSyncCell<T>]>` drop normally.
Because `UnsafeSyncCell<T>` has a `Drop` impl that runs `assume_init_drop` on its inner `MaybeUninit<T>`, the source-side `T` values are dropped at the end of `new`, while bitwise duplicates (carrying the same heap pointers for `String`, `Box`, `Vec`, `Arc`, …) remain inside the mmap region. When the ring buffer is later destructed, the destructor's `drop_in_place` over the slice runs `UnsafeSyncCell::drop` a second time on every cell — a deterministic double-free of every heap-owning element. Reachable from 100% safe Rust.
## Trigger
```rust let v: Vec<Vec<u32>> = (0..1024).map(|i| vec![i, i+1, i+2]).collect(); let rb: oneringbuf::SharedVmemRB<Vec<u32>> = oneringbuf::SharedVmemRB::from(v); drop(rb); // glibc: free(): double free detected in tcache 2 -> abort // ASan: AddressSanitizer: attempting double-free ```
Any `T` with a non-trivial `Drop` reproduces deterministically.
## Fix
Fixed in `0.7.1` via upstream PR [skilvingr/rust-oneringbuf#3](https://github.com/skilvingr/rust-oneringbuf/pull/3), which deallocates the source `Box<[UnsafeSyncCell<T>]>` without running per-element `Drop` after the bytes have been copied into the mmap region. Vulnerable versions (`< 0.7.1`) have been yanked from crates.io.
Are you affected?
Enter the version of the package you're using.
Affected packages
0.0.0-0Fixed in: 0.7.1Upgrade oneringbuf to 0.7.1 or newer (ecosystem crates.io).