Skip to content

miri reports undefined behavior #13

@eric-seppanen

Description

@eric-seppanen

This unit test reports undefined behavior in miri:

#[test]
fn oops() {
    executor::run(async {
        let (s, r) = async_channel::unbounded();

        std::thread::spawn(move || {
            s.send_blocking("42").unwrap();
        });

        // Receive the value.
        let res = r.recv().await;
        assert_eq!(res, Ok("42"));
    })
}

Miri output:

test tests::oops ... error: Undefined Behavior: trying to retag from <90602> for SharedReadWrite permission at alloc22794[0x0], but that tag does not exist in the borrow stack for this location
   --> /home/eric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/non_null.rs:401:18
    |
401 |         unsafe { &*self.as_ptr().cast_const() }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |                  |
    |                  trying to retag from <90602> for SharedReadWrite permission at alloc22794[0x0], but that tag does not exist in the borrow stack for this location
    |                  this error occurs as part of retag at alloc22794[0x0..0x28]
    |
    = 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: <90602> was created by a SharedReadWrite retag at offsets [0x18..0x51]
   --> src/lib.rs:6:9
    |
6   | /         executor::run(async {
7   | |             let (s, r) = async_channel::unbounded();
8   | |
9   | |             std::thread::spawn(move || {
...   |
15  | |             assert_eq!(res, Ok("42"));
16  | |         })
    | |__________^
    = note: BACKTRACE (of the first span) on thread `tests::oops`:
    = note: inside `std::ptr::NonNull::<alloc::sync::ArcInner<executor::Task<()>>>::as_ref::<'_>` at /home/eric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/non_null.rs:401:18: 401:46
    = note: inside `std::sync::Arc::<executor::Task<()>>::inner` at /home/eric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:1796:18: 1796:35
    = note: inside `<std::sync::Arc<executor::Task<()>> as std::clone::Clone>::clone` at /home/eric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/sync.rs:2075:24: 2075:36
    = note: inside `<std::mem::ManuallyDrop<std::sync::Arc<executor::Task<()>>> as std::clone::Clone>::clone` at /home/eric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/manually_drop.rs:51:5: 51:13
    = note: inside `woke::increase_refcount::<executor::Task<()>>` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/woke-0.0.4/src/lib.rs:38:44: 38:55
    = note: inside `woke::clone_arc_raw::<executor::Task<()>>` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/woke-0.0.4/src/lib.rs:42:5: 42:33
    = note: inside `<std::task::Waker as std::clone::Clone>::clone` at /home/eric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/task/wake.rs:514:29: 514:71
    = note: inside `event_listener::TaskRef::<'_>::into_task` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-5.2.0/src/lib.rs:1322:47: 1322:60
    = note: inside `event_listener::sys::<impl event_listener::Inner<()>>::register` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-5.2.0/src/std.rs:165:45: 165:61
    = note: inside `event_listener::InnerListener::<(), std::sync::Arc<event_listener::Inner<()>>>::poll_internal` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-5.2.0/src/lib.rs:1159:15: 1160:65
    = note: inside `<event_listener::EventListener as std::future::Future>::poll` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-5.2.0/src/lib.rs:878:17: 878:54
    = note: inside `<event_listener_strategy::NonBlocking<'_> as event_listener_strategy::Strategy<'_>>::poll::<(), event_listener::EventListener>` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-strategy-0.5.0/src/lib.rs:467:20: 472:23
    = note: inside `<async_channel::RecvInner<'_, &str> as event_listener_strategy::EventListenerFuture>::poll_with_strategy::<'_, event_listener_strategy::NonBlocking<'_>>` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-channel-2.2.0/src/lib.rs:1196:24: 1196:66
    = note: inside `<event_listener_strategy::FutureWrapper<async_channel::RecvInner<'_, &str>> as std::future::Future>::poll` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-strategy-0.5.0/src/lib.rs:381:9: 383:70
    = note: inside `<async_channel::Recv<'_, &str> as std::future::Future>::poll` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/event-listener-strategy-0.5.0/src/lib.rs:259:17: 259:52
note: inside closure
   --> src/lib.rs:14:32
    |
14  |             let res = r.recv().await;
    |                                ^^^^^
    = note: inside `<std::sync::Arc<executor::Task<()>> as executor::Pendable>::is_pending` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/executor-0.8.4/src/lib.rs:47:18: 47:47
    = note: inside `executor::Executor::poll_tasks` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/executor-0.8.4/src/lib.rs:85:16: 85:33
    = note: inside `executor::Executor::run::<()>` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/executor-0.8.4/src/lib.rs:58:9: 58:26
    = note: inside `executor::run::<(), {async block@src/lib.rs:6:23: 16:10}>` at /home/eric/.cargo/registry/src/index.crates.io-6f17d22bba15001f/executor-0.8.4/src/lib.rs:98:5: 98:50
note: inside `tests::oops`
   --> src/lib.rs:6:9
    |
6   | /         executor::run(async {
7   | |             let (s, r) = async_channel::unbounded();
8   | |
9   | |             std::thread::spawn(move || {
...   |
15  | |             assert_eq!(res, Ok("42"));
16  | |         })
    | |__________^

This is with async-channel = "2.2.0", executor = "0.8.4".

The toolchain that was used:

$ rustc +nightly -V
rustc 1.78.0-nightly (d18480b84 2024-03-04)

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