Repository: rust-lang/miri

Issue #2104: Allocators that "shrink" allocations to fit the request cause Stacked Borrows errors when used with Box
Created: 2022-05-07T17:09:33Z
When a Box allocator creates an allocation and returns only a part of that to Box, there will be Stacked Borrows errors when the Box is deallocated. This is because the pointer lost the provenance for the other parts of memory outside the Box, and hence does not have the right to deallocate them.
This affects, in particular, the System allocator on Windows:
#![feature(allocator_api)]

#[repr(align(32))]
struct VeryAligned(u8);

fn main() {
    let _ = Box::new_in(VeryAligned(0), std::alloc::System);
}
Also see the discussion on Zulip.

Duplicate issue #2678: Stacked borrows error when replacing the default allocator with... the default allocator
Created: 2022-11-18T22:24:17Z
I have some code which passes MIRI. However, when I replace the default allocator with the System allocator, it gives a stacked borrows error:
#[global_allocator]
static ALLOCATOR: System = System;
This implies something very weird is going on. None of my code is in the backtrace.
This is the full error:
error: Undefined Behavior: attempting a read access using <3316050> at alloc95894[0x8], but that tag does not exist in the borrow stack for this location
   --> C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\alloc.rs:217:26
    |
217 |                 unsafe { ptr::read((ptr as *mut Header).sub(1)).0 }
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                          |
    |                          attempting a read access using <3316050> at alloc95894[0x8], but that tag does not exist in the borrow stack for this location
    |                          this error occurs as part of an access at alloc95894[0x8..0x10]
    |
    = 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: <3316050> was created by a Unique retag at offsets [0x10..0x210]
    = note: BACKTRACE:
    = note: inside `std::sys::windows::alloc::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sys\windows\alloc.rs:217:26
note: inside `tests::_::__rg_dealloc` at src\lib.rs:53:23
   --> src\lib.rs:53:23
    |
52  |     #[global_allocator]
    |     ------------------- in this procedural macro expansion
53  |     static ALLOCATOR: System = System;
    |                       ^^^^^^
    = note: inside `std::alloc::dealloc` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:113:14
    = note: inside `<std::alloc::Global as std::alloc::Allocator>::deallocate` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:250:22
    = note: inside `alloc::alloc::box_free::<std::sync::mpmc::counter::Counter<std::sync::mpmc::list::Channel<test::event::CompletedTest>>, std::alloc::Global>` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\alloc.rs:348:9
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<std::sync::mpmc::counter::Counter<std::sync::mpmc::list::Channel<test::event::CompletedTest>>>> - shim(Some(std::boxed::Box<std::sync::mpmc::counter::Counter<std::sync::mpmc::list::Channel<test::event::CompletedTest>>>))` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:490:1
    = note: inside `std::mem::drop::<std::boxed::Box<std::sync::mpmc::counter::Counter<std::sync::mpmc::list::Channel<test::event::CompletedTest>>>>` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\mem\mod.rs:979:24
    = note: inside `std::sync::mpmc::counter::Sender::<std::sync::mpmc::list::Channel<test::event::CompletedTest>>::release::<[closure@<std::sync::mpmc::Sender<test::event::CompletedTest> as std::ops::Drop>::drop::{closure#1}]>` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sync\mpmc\counter.rs:66:17
    = note: inside `<std::sync::mpmc::Sender<test::event::CompletedTest> as std::ops::Drop>::drop` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\sync\mpmc\mod.rs:231:45
    = note: inside `std::ptr::drop_in_place::<std::sync::mpmc::Sender<test::event::CompletedTest>> - shim(Some(std::sync::mpmc::Sender<test::event::CompletedTest>))` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:490:1
    = note: inside `std::ptr::drop_in_place::<std::sync::mpsc::Sender<test::event::CompletedTest>> - shim(Some(std::sync::mpsc::Sender<test::event::CompletedTest>))` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:490:1
    = note: inside `test::run_tests::<[closure@test::run_tests_console::{closure#2}]>` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\test\src\lib.rs:455:1
    = note: inside `test::run_tests_console` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\test\src\console.rs:293:5
    = note: inside `test::test_main` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\test\src\lib.rs:140:15
    = note: inside `test::test_main_static` at C:\Users\diggs\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\test\src\lib.rs:159:5
    = note: inside `main`
    = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info)

As you can see, I'm running MIRI on windows.

Closing comment (2022-11-19T09:11:26Z): In order to use mockalloc you need to wrap a "default" allocator. I was doing that by wrapping System. Is there some other way to really get the default allocator?

I'm not disputing that setting System as the global allocator should work. :) It's just pretty hard for Windows -- we need to replace Stacked Borrows by something new altogether. The good news is that I am actively working with an intern on exactly that project.
I don't think there is a new bug here so I'll close this as a duplicate of #2104. I still feel like if you are not actually setting the global allocator, you better not rely on it actually being System -- IOW, I still think this code should raise an error. But that would be a separate issue.