Skip to content

libtest UB with custom allocator, per miri #138839

@alecmocatta

Description

@alecmocatta

I tried this code:

git clone https://github.com/alecmocatta/memcheck
cargo miri test

I expected to see this happen: test passes.

Instead, this happened:

error: Undefined Behavior: trying to retag from <98686> for Unique permission at alloc46622[0x38], but that tag does not exist in the borrow stack for this location
   --> /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mut_ptr.rs:683:18
    |
683 |         unsafe { &mut *self }
    |                  ^^^^^^^^^^
    |                  |
    |                  trying to retag from <98686> for Unique permission at alloc46622[0x38], but that tag does not exist in the borrow stack for this location
    |                  this error occurs as part of retag at alloc46622[0x38..0x42]
    |
    = 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: <98686> was created by a Unique retag at offsets [0x0..0x38]
    = note: BACKTRACE (of the first span):
    = note: inside `std::ptr::mut_ptr::<impl *mut memcheck::Check>::as_mut_unchecked::<'_>` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mut_ptr.rs:683:18: 683:28
note: inside `<memcheck::Memcheck<std::alloc::System> as std::alloc::GlobalAlloc>::dealloc`
   --> /Users/alecmocatta/Downloads/memcheck/src/lib.rs:42:15
    |
42  |         let check = ptr.add(l.size()).cast::<Check>().as_mut_unchecked();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `_::__rust_dealloc`
   --> tests/test.rs:9:19
    |
8   | #[global_allocator]
    | ------------------- in this procedural macro expansion
9   | static ALLOCATOR: Memcheck<alloc::System> = Memcheck::new(alloc::System);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `alloc::raw_vec::RawVecInner::deallocate` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec/mod.rs:757:17: 757:51
    = note: inside `<alloc::raw_vec::RawVec<getopts::Opt> as std::ops::Drop>::drop` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/raw_vec/mod.rs:406:18: 406:50
    = note: inside `std::ptr::drop_in_place::<alloc::raw_vec::RawVec<getopts::Opt>> - shim(Some(alloc::raw_vec::RawVec<getopts::Opt>))` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:523:1: 523:56
    = note: inside `std::ptr::drop_in_place::<std::vec::Vec<getopts::Opt>> - shim(Some(std::vec::Vec<getopts::Opt>))` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:523:1: 523:56
    = note: inside `std::ptr::drop_in_place::<getopts::Opt> - shim(Some(getopts::Opt))` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:523:1: 523:56
    = note: inside `std::ptr::drop_in_place::<[getopts::Opt]> - shim(Some([getopts::Opt]))` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:523:1: 523:56
    = note: inside `<std::vec::Vec<getopts::Opt> as std::ops::Drop>::drop` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3798:13: 3798:91
    = note: inside `std::ptr::drop_in_place::<std::vec::Vec<getopts::Opt>> - shim(Some(std::vec::Vec<getopts::Opt>))` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:523:1: 523:56
    = note: inside `std::ptr::drop_in_place::<getopts::Matches> - shim(Some(getopts::Matches))` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:523:1: 523:56
    = note: inside `test::cli::parse_opts_impl` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/test/src/cli.rs:311:1: 311:2
    = note: inside `test::test::parse_opts` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/test/src/cli.rs:218:23: 218:47
    = note: inside `test::test_main` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/test/src/lib.rs:101:26: 101:47
    = note: inside `test::test_main_static` at /Users/alecmocatta/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/src/rust/library/test/src/lib.rs:173:5: 173:40
    = note: inside `main`

There could be a bug in my GlobalAlloc impl, though miri raises no UB when using it outside of libtest.

This crate was written to debug occasionally seeing this assertion #124671 still being hit in production.

Meta

rustc 1.87.0-nightly (be73c1f46 2025-03-21)
binary: rustc
commit-hash: be73c1f4617c97bce81b2694a767353300a75072
commit-date: 2025-03-21
host: aarch64-apple-darwin
release: 1.87.0-nightly
LLVM version: 20.1.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-discussionCategory: Discussion or questions that doesn't represent real issues.T-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions