- Reported
-
- Issued
-
- Package
-
mutringbuf
(crates.io)
- Type
-
INFO
Unsound
- Categories
-
- Keywords
-
#double-free
#use-after-free
#vmem
#drop
#unmaintained
- References
-
- Patched
-
no patched versions
- Affected Functions
- Version
mutringbuf::VmemStorage::new
-
Description
mutringbuf is the archived predecessor of oneringbuf — the crate was renamed and the GitHub repository was archived on 2025-11-20. All released versions up to 1.0.0 carry the same vmem-feature double-free bug that affects oneringbuf, with the same code paths and the same reproduction shape.
When the vmem feature is enabled, VmemStorage<T>::new(Box<[UnsafeSyncCell<T>]>) (and every public constructor that funnels through it) 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 remain inside the mmap region. The ring-buffer destructor then runs UnsafeSyncCell::drop a second time on every cell — a deterministic double-free of every heap-owning element. Reachable from 100% safe Rust.
Trigger
let v: Vec<Vec<u32>> = (0..1024).map(|i| vec![i, i+1, i+2]).collect();
let rb: mutringbuf::SharedVmemRB<Vec<u32>> = mutringbuf::SharedVmemRB::from(v);
drop(rb);
// glibc: free(): double free detected in tcache 2 -> abort
Fix
mutringbuf is no longer maintained. The author renamed the crate to oneringbuf and shipped the fix as oneringbuf 0.7.1 (upstream PR skilvingr/rust-oneringbuf#3). All mutringbuf versions have been yanked from crates.io. Users should migrate to oneringbuf >= 0.7.1.
See the parallel advisory for the oneringbuf crate for the full technical write-up of the bug.
Advisory available under CC0-1.0
license.