fitzgen / bumpalo

A fast bump allocation arena for Rust
https://docs.rs/bumpalo
Apache License 2.0
1.34k stars 109 forks source link

Miri error with `allocator_api` and `Box`-pointer roundtrips #247

Closed zetah11 closed 1 month ago

zetah11 commented 1 month ago

Hi, thank you for the great work!

Using the allocator_api feature of this crate and nightly, I noticed that Miri does not like this:

#![feature(allocator_api)]

fn main() {
    let bump = bumpalo::Bump::new();

    let a = Box::into_raw(Box::new_in(1u8, &bump));
    drop(unsafe { Box::from_raw_in(a, &bump) });

    let _b = Box::new_in(2u16, &bump);
}

Miri error:

error: Undefined Behavior: trying to retag from <2737> for SharedReadWrite permission at alloc1066[0x1be], but that tag does not exist in the borrow stack for this location
   --> C:\...\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\boxed.rs:385:13
    |
385 |             boxed.as_mut_ptr().write(x);
    |             ^^^^^
    |             |
    |             trying to retag from <2737> for SharedReadWrite permission at alloc1066[0x1be], but that tag does not exist in the borrow stack for this location
    |             this error occurs as part of two-phase retag at alloc1066[0x1be..0x1c0]
    |
    = 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
help: <2737> was created by a SharedReadWrite retag at offsets [0x1bf..0x1c0]
   --> src/main.rs:6:13
    |
6   |     let a = Box::into_raw(Box::new_in(1u8, &bump));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<u16, &bumpalo::Bump>::new_in` at C:\...\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\boxed.rs:385:13: 385:18
note: inside `main`
   --> src/main.rs:9:14
    |
9   |     let _b = Box::new_in(2u16, &bump);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^

The exact types of the allocations involved does not matter much, only that _b allocates something with an alignment larger than a.

I'm pretty new to Miri, so I'm not quite sure what the issue is exactly. It seems like the combination of the retagging in Box::into_raw, the deallocation in of the recreated box, and the layout differences are the essential parts. This is not triggered if the Box is dropped without the pointer roundtrip, nor with bumpalo::boxed::Box, nor when using bump.reset() instead of drop. It does show up when using allocator-api2 and its Box.