Hello,
First, thank you for your work on the direct_ring_buffer library.
Our team is developing a static analysis tool for Rust designed to detect potential soundness issues. During our testing, our tool flagged a potential issue in this crate. We have investigated further and confirmed with Miri that the public safe function create_ring_buffer can lead to Undefined Behavior.
|
pub fn create_ring_buffer<T: Copy>(size: usize) -> (Producer<T>, Consumer<T>) { |
|
let buffer = Arc::new(DirectRingBuffer { |
|
elements: UnsafeCell::new({ |
|
let mut vec = Vec::<T>::with_capacity(size); |
|
unsafe { vec.set_len(size) }; |
|
vec.into_boxed_slice() |
|
}), |
|
used: AtomicUsize::new(0), |
|
}); |
|
( |
|
Producer { |
|
buffer: Arc::clone(&buffer), |
|
index: 0, |
|
}, |
|
Consumer { buffer, index: 0 }, |
|
) |
|
} |
The function allocates a buffer using Vec::with_capacity followed by an unsafe call to set_len. This creates a Box<[T]> containing uninitialized memory. This leads to immediate UB when a function like producer.write_slices later creates a typed slice (e.g., &mut [bool]) over this uninitialized memory, as this violates Rust's validity invariants. A safe function should not be able to cause UB, regardless of the input.
POC:
use direct_ring_buffer::create_ring_buffer;
fn main() {
let (mut producer, _consumer) = create_ring_buffer::<bool>(10);
producer.write_slices(|_slice, _| {
0
}, None);
}
Verified with miri:
cuu@ccuu-H3CDesk-D500t:~/Desktop/rust/test1$ cargo +nightly miri run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
Running `/home/ccuu/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/test1`
error: Undefined Behavior: trying to retag from <800> for Unique permission at alloc233[0x1], but that tag does not exist in the borrow stack for this location
--> /home/ccuu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/direct_ring_buffer-0.2.1/src/lib.rs:99:30
|
99 | unsafe { from_raw_parts_mut(buf, len) },
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of retag at alloc233[0x0..0xa]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
Hello,
First, thank you for your work on the direct_ring_buffer library.
Our team is developing a static analysis tool for Rust designed to detect potential soundness issues. During our testing, our tool flagged a potential issue in this crate. We have investigated further and confirmed with Miri that the public safe function
create_ring_buffercan lead to Undefined Behavior.direct_ring_buffer/src/lib.rs
Lines 455 to 471 in 09022f6
The function allocates a buffer using Vec::with_capacity followed by an unsafe call to
set_len. This creates a Box<[T]> containing uninitialized memory. This leads to immediate UB when a function like producer.write_slices later creates a typed slice (e.g., &mut [bool]) over this uninitialized memory, as this violates Rust's validity invariants. A safe function should not be able to cause UB, regardless of the input.POC:
Verified with miri: