fcplug icon indicating copy to clipboard operation
fcplug copied to clipboard

Potential Undefined Behavior in Buffer struct found

Open lewismosciski opened this issue 2 months ago • 0 comments

Hello,

We are currently developing a static analysis tool for Rust, and during our testing, we analyzed fcplug. We believe we have identified two instances of Undefined Behavior in the Buffer struct, which we were able to confirm using miri.

Double Free due to Buffer being Copy

The Buffer struct derives #[derive(Copy)]. However, Buffer::from_vec takes ownership of a Vec's memory. Because the Buffer is Copy, this unique ownership can be duplicated, leading to a double-free when the public free_buffer function is called on both copies.

https://github.com/andeya/fcplug/blob/04fd56ad2331af25627800aeebc8f00376f9ca3d/rust/fcplug/src/lib.rs#L25-L27

POC:

fn main() {
    let v = vec![1, 2, 3, 4, 5];
    let b1 = Buffer::from_vec(v);
    let b2 = b1;
    println!("b1 ptr: {:?}", b1.ptr);
    println!("b2 ptr: {:?}", b2.ptr);
    free_buffer(b1);
    free_buffer(b2);
}

miri output:

b1 ptr: 0x20adf
b2 ptr: 0x20adf
error: Undefined Behavior: pointer not dereferenceable: alloc210 has been freed, so this pointer is dangling
   --> /home/ccuu/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:804:1
    |
804 | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior

Use-After-Free due to unsound from_vec_mut

The Buffer::from_vec_mut function takes a &mut Vec but returns a Buffer that is not tied to the lifetime of the original Vec. This allows a Buffer to be created that outlives the Vec it borrows from. When the Vec is dropped, the Buffer is left holding a dangling pointer.

https://github.com/andeya/fcplug/blob/04fd56ad2331af25627800aeebc8f00376f9ca3d/rust/fcplug/src/lib.rs#L153-L164

POC:

fn main() {
    let b: Buffer;
    {
        let mut v = vec![1, 2, 3, 4, 5];
        b = Buffer::from_vec_mut(&mut v);
    }
    let _data = b.read();
}

miri output:

error: Undefined Behavior: pointer not dereferenceable: alloc203 has been freed, so this pointer is dangling
   --> /home/ccuu/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/fcplug-0.4.5/src/lib.rs:108:27
    |
108 |             unsafe { Some(std::slice::from_raw_parts(self.ptr, self.len)) }
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior

lewismosciski avatar Oct 19 '25 12:10 lewismosciski