Skip to content

Soundness Issue: create_ring_buffer can lead to Undefined Behavior #1

@lewismosciski

Description

@lewismosciski

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions