Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICE using -Zmiri-tag-raw-pointers: 'we should never pop more than one frame at once' #2081

Closed
y86-dev opened this issue Apr 21, 2022 · 8 comments

Comments

@y86-dev
Copy link
Contributor

y86-dev commented Apr 21, 2022

I tried this code (havent tried to reduce this yet, because i discovered this while trying to solve another bug):

Code
#![deny(unsafe_op_in_unsafe_fn)]
use core::{
    marker::PhantomPinned,
    mem::{self, ManuallyDrop, MaybeUninit},
    pin::Pin,
    ptr::{addr_of, addr_of_mut},
};

#[repr(transparent)]
struct UnsafeAliasCell<T> {
    value: T,
    _pin: PhantomPinned,
}

impl<T> UnsafeAliasCell<T> {
    pub fn new(value: T) -> Self {
        Self {
            value,
            _pin: PhantomPinned,
        }
    }

    pub fn get(&mut self) -> *mut T {
        addr_of_mut!(self.value)
    }
}

#[repr(C)]
pub struct PtrBufUninit<T, const N: usize> {
    idx: MaybeUninit<*const T>,
    end: MaybeUninit<*const T>,
    buf: UnsafeAliasCell<[ManuallyDrop<T>; N]>,
}

struct PtrBufUninitProj<'pin, T, const N: usize> {
    idx: &'pin mut MaybeUninit<*const T>,
    end: &'pin mut MaybeUninit<*const T>,
    buf: &'pin mut UnsafeAliasCell<[ManuallyDrop<T>; N]>,
}

#[repr(C)]
pub struct PtrBuf<T, const N: usize> {
    idx: *const T,
    end: *const T,
    buf: UnsafeAliasCell<[ManuallyDrop<T>; N]>,
}

struct PtrBufProj<'pin, T, const N: usize> {
    idx: &'pin mut *const T,
    end: &'pin mut *const T,
    #[allow(dead_code)]
    buf: &'pin mut UnsafeAliasCell<[ManuallyDrop<T>; N]>,
}

impl<T, const N: usize> PtrBufUninit<T, N> {
    pub fn init(mut self: Pin<Box<Self>>) -> Pin<Box<PtrBuf<T, N>>> {
        let this = self.as_mut().project();
        let ptr = this.buf.get() as *const T;
        this.idx.write(ptr);
        let ptr = unsafe {
            //ptr.offset(N as isize - 1)
            // SAFETY: buf is a valid pointer
            addr_of!((*(this.buf.get() as *mut [ManuallyDrop<T>; N]))[N - 1])
                as *const ManuallyDrop<T> as *const T
        };
        this.end.write(ptr);
        unsafe {
            // SAFETY: we do not move the contents of the box
            let this = Pin::into_inner_unchecked(self);
            let this = Box::from_raw(Box::into_raw(this) as *mut PtrBuf<T, N>);
            Pin::new_unchecked(this)
        }
    }

    fn project(self: Pin<&mut Self>) -> PtrBufUninitProj<'_, T, N> {
        // SAFETY: we do not structually pin anything, we only need buf to stay where it is.
        let this = unsafe { Pin::get_unchecked_mut(self) };
        PtrBufUninitProj {
            idx: &mut this.idx,
            end: &mut this.end,
            buf: &mut this.buf,
        }
    }
}

impl<T, const N: usize> PtrBuf<T, N> {
    fn project(self: Pin<&mut Self>) -> PtrBufProj<'_, T, N> {
        // SAFETY: we do not structually pin anything, we only need buf to stay where it is.
        let this = unsafe { Pin::get_unchecked_mut(self) };
        PtrBufProj {
            idx: &mut this.idx,
            end: &mut this.end,
            buf: &mut this.buf,
        }
    }
}

impl<T, const N: usize> From<[T; N]> for PtrBufUninit<T, N> {
    fn from(arr: [T; N]) -> Self {
        assert_ne!(N, 0);
        assert!(
            N < isize::MAX as usize,
            "N cannot be bigger than isize::MAX"
        );
        Self {
            idx: MaybeUninit::uninit(),
            end: MaybeUninit::uninit(),
            buf: unsafe {
                // SAFETY: T and ManuallyDrop<T> have the same layout, so [T; N] and
                // [ManuallyDrop<T>; N] also have the same layout
                let ptr = addr_of!(arr) as *const [T; N] as *const [ManuallyDrop<T>; N];
                mem::forget(arr);
                UnsafeAliasCell::new(ptr.read())
            },
        }
    }
}

impl<T, const N: usize> PtrBuf<T, N> {
    pub fn next(self: Pin<&mut Self>) -> Option<T> {
        let this = self.project();
        if this.idx > this.end {
            None
        } else {
            let val = unsafe {
                // SAFETY: we checked if idx is in bounds before and
                // we read the value at idx and offset idx, this value is never read again
                this.idx.read()
            };
            unsafe {
                // SAFETY: we are still in bounds of buf (end stores the end of buf)
                // and adding size_of::<T>() will only land us at most one byte of buf.
                *this.idx = this.idx.offset(1);
            }
            Some(val)
        }
    }
}

impl<T, const N: usize> Drop for PtrBuf<T, N> {
    fn drop(&mut self) {
        fn pinned_drop<T, const N: usize>(mut this: Pin<&mut PtrBuf<T, N>>) {
            while let Some(x) = this.as_mut().next() {
                drop(x);
            }
        }
        pinned_drop(unsafe { Pin::new_unchecked(self) });
    }
}

impl<T, const N: usize> Drop for PtrBufUninit<T, N> {
    fn drop(&mut self) {
        let slice = unsafe {
            // We did not access buf anywhere yet
            &mut *self.buf.get()
        };
        for x in slice {
            unsafe {
                // SAFETY: we are dropping ourselves and thus this is subject to the same
                // invariants
                ManuallyDrop::drop(x);
            }
        }
    }
}

fn main() {
    let buf: PtrBufUninit<i32, 5> = [42, -42, 1337, 0, 6].into();
    let mut buf = Box::pin(buf).init();
    assert_eq!(buf.as_mut().next(), Some(42));
    assert_eq!(buf.as_mut().next(), Some(-42));
    assert_eq!(buf.as_mut().next(), Some(1337));
    assert_eq!(buf.as_mut().next(), Some(0));
    assert_eq!(buf.as_mut().next(), Some(6));
    assert_eq!(buf.as_mut().next(), None);
}
Then when running under miri with
MIRIFLAGS="-Zmiri-tag-raw-pointers -Zmiri-track-pointer-tag=2500" cargo miri run
Stacktrace
note: tracking was triggered
   --> ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:634:13
    |
634 |             ManuallyDrop::into_inner(self.value)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ created tag 2500
    |
    = note: inside `std::mem::MaybeUninit::<[std::mem::ManuallyDrop<i32>; 5]>::assume_init` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/mem/maybe_uninit.rs:634:13
    = note: inside `std::ptr::read::<[std::mem::ManuallyDrop<i32>; 5]>` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1097:9
    = note: inside `std::ptr::const_ptr::<impl *const [std::mem::ManuallyDrop<i32>; 5]>::read` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/const_ptr.rs:941:18
note: inside `<PtrBufUninit<i32, 5_usize> as std::convert::From<[i32; 5]>>::from` at src/main.rs:113:38
   --> src/main.rs:113:38
    |
113 |                 UnsafeAliasCell::new(ptr.read())
    |                                      ^^^^^^^^^^
    = note: inside `<[i32; 5] as std::convert::Into<PtrBufUninit<i32, 5_usize>>>::into` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:550:9
note: inside `main` at src/main.rs:168:37
   --> src/main.rs:168:37
    |
168 |     let buf: PtrBufUninit<i32, 5> = [42, -42, 1337, 0, 6].into();
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

thread 'rustc' panicked at 'we should never pop more than one frame at once', src/tools/miri/src/diagnostics.rs:377:17
stack backtrace:
   0:     0x7f4767bec85d - std::backtrace_rs::backtrace::libunwind::trace::hd79e9b51bb0b02a3
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
   1:     0x7f4767bec85d - std::backtrace_rs::backtrace::trace_unsynchronized::hc4b2624d11f57391
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
   2:     0x7f4767bec85d - std::sys_common::backtrace::_print_fmt::h5b920b6df28041d5
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/sys_common/backtrace.rs:66:5
   3:     0x7f4767bec85d - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h01f2db48eea34166
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/sys_common/backtrace.rs:45:22
   4:     0x7f4767c47efc - core::fmt::write::h743b8fce003c331c
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/core/src/fmt/mod.rs:1194:17
   5:     0x7f4767bde041 - std::io::Write::write_fmt::h55edc38b905db9b5
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/io/mod.rs:1655:15
   6:     0x7f4767bef575 - std::sys_common::backtrace::_print::h72c54a6b7a86b7bf
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/sys_common/backtrace.rs:48:5
   7:     0x7f4767bef575 - std::sys_common::backtrace::print::h8b541992f5fa33c9
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/sys_common/backtrace.rs:35:9
   8:     0x7f4767bef575 - std::panicking::default_hook::{{closure}}::h47e8a61e5844dea4
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/panicking.rs:295:22
   9:     0x7f4767bef1e9 - std::panicking::default_hook::h65ae1796882c178c
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/panicking.rs:314:9
  10:     0x7f476838d5a1 - rustc_driver[caca827775d68846]::DEFAULT_HOOK::{closure#0}::{closure#0}
  11:     0x7f4767befd46 - std::panicking::rust_panic_with_hook::h1c3eee211b989bad
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/panicking.rs:702:17
  12:     0x7f4767befb09 - std::panicking::begin_panic_handler::{{closure}}::h653627205f5b2cdc
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/panicking.rs:586:13
  13:     0x7f4767becd14 - std::sys_common::backtrace::__rust_end_short_backtrace::h36d845a914b6aae7
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/sys_common/backtrace.rs:138:18
  14:     0x7f4767bef879 - rust_begin_unwind
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/panicking.rs:584:5
  15:     0x7f4767bb4bd3 - core::panicking::panic_fmt::hb6389d787a80a806
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/core/src/panicking.rs:142:14
  16:     0x5646cd103156 - <std[fd2a1eaf3e081d4d]::thread::local::LocalKey<core[864d7ae58f623181]::cell::RefCell<alloc[642b2cd0ec1e1a81]::vec::Vec<miri[11bda64e92b8a89f]::diagnostics::NonHaltingDiagnostic>>>>::with::<<rustc_const_eval[ec16a9026af29337]::interpret::eval_context::InterpCx<miri[11bda64e92b8a89f]::machine::Evaluator> as miri[11bda64e92b8a89f]::diagnostics::EvalContextExt>::process_diagnostics::{closure#0}, ()>
  17:     0x5646cd0f7159 - miri[11bda64e92b8a89f]::eval::eval_entry
  18:     0x5646cd06a902 - <rustc_interface[dacacaf3651fe347]::passes::QueryContext>::enter::<<miri[aaa733ecb7479b45]::MiriCompilerCalls as rustc_driver[caca827775d68846]::Callbacks>::after_analysis::{closure#0}, ()>
  19:     0x5646cd06346e - <miri[aaa733ecb7479b45]::MiriCompilerCalls as rustc_driver[caca827775d68846]::Callbacks>::after_analysis
  20:     0x7f476a3a1ab5 - <rustc_interface[dacacaf3651fe347]::interface::Compiler>::enter::<rustc_driver[caca827775d68846]::run_compiler::{closure#1}::{closure#2}, core[864d7ae58f623181]::result::Result<core[864d7ae58f623181]::option::Option<rustc_interface[dacacaf3651fe347]::queries::Linker>, rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>>
  21:     0x7f476a3cb3ff - rustc_span[ff646084812721ee]::with_source_map::<core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>, rustc_interface[dacacaf3651fe347]::interface::create_compiler_and_run<core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>, rustc_driver[caca827775d68846]::run_compiler::{closure#1}>::{closure#1}>
  22:     0x7f476a3b5d64 - rustc_interface[dacacaf3651fe347]::interface::create_compiler_and_run::<core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>, rustc_driver[caca827775d68846]::run_compiler::{closure#1}>
  23:     0x7f476a39efa1 - <scoped_tls[d6203f3b3010b98e]::ScopedKey<rustc_span[ff646084812721ee]::SessionGlobals>>::set::<rustc_interface[dacacaf3651fe347]::interface::run_compiler<core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>, rustc_driver[caca827775d68846]::run_compiler::{closure#1}>::{closure#0}, core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>>
  24:     0x7f476a3b854f - std[fd2a1eaf3e081d4d]::sys_common::backtrace::__rust_begin_short_backtrace::<rustc_interface[dacacaf3651fe347]::util::run_in_thread_pool_with_globals<rustc_interface[dacacaf3651fe347]::interface::run_compiler<core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>, rustc_driver[caca827775d68846]::run_compiler::{closure#1}>::{closure#0}, core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>>::{closure#0}, core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>>
  25:     0x7f476a3b8689 - <<std[fd2a1eaf3e081d4d]::thread::Builder>::spawn_unchecked_<rustc_interface[dacacaf3651fe347]::util::run_in_thread_pool_with_globals<rustc_interface[dacacaf3651fe347]::interface::run_compiler<core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>, rustc_driver[caca827775d68846]::run_compiler::{closure#1}>::{closure#0}, core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>>::{closure#0}, core[864d7ae58f623181]::result::Result<(), rustc_errors[14f27e81a88a2c7]::ErrorGuaranteed>>::{closure#1} as core[864d7ae58f623181]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  26:     0x7f4767bf9bf3 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h211dae6d8dec3611
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/alloc/src/boxed.rs:1866:9
  27:     0x7f4767bf9bf3 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::hb54334e8a7bb1f12
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/alloc/src/boxed.rs:1866:9
  28:     0x7f4767bf9bf3 - std::sys::unix::thread::Thread::new::thread_start::hf8b57655f2f2e68e
                               at /rustc/4ca19e09d302a4cbde14f9cb1bc109179dc824cd/library/std/src/sys/unix/thread.rs:108:17
  29:     0x7f47678b6b1a - start_thread
  30:     0x7f476793b660 - __GI___clone3
  31:                0x0 - <unknown>

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: rustc 1.62.0-nightly (4ca19e09d 2022-04-19) running on x86_64-unknown-linux-gnu

note: compiler flags: --crate-type bin -C embed-bitcode=no -C debuginfo=2 -C incremental -Z miri-tag-raw-pointers -Z miri-track-pointer-tag=2500

note: some of the compiler flags provided by cargo are hidden

query stack during panic:
end of query stack

It also occures on the current master branch (3ac7ca4).

Removing the -Zmiri-track-raw-pointers produces no ICE.

@y86-dev y86-dev changed the title ICE using -Zmiri-track-raw-pointers: 'we should never pop more than one frame at once' ICE using -Zmiri-tag-raw-pointers: 'we should never pop more than one frame at once' Apr 21, 2022
@y86-dev
Copy link
Contributor Author

y86-dev commented Apr 21, 2022

It also occurs with:

  • 79
  • 82-87
  • 309
  • 312-317
  • 410
  • 413-418
  • 2251
  • 2257
  • 2501
  • 3633-3638
  • 3645-3655
  • 3662
  • 3663
  • 3666-3676
  • 3680-3688
  • 3771-3775
  • 3778-3781

(tested up to 6000)

@y86-dev
Copy link
Contributor Author

y86-dev commented Apr 21, 2022

The errors at 79 and 82-87 also seem to occur with a new project.

@RalfJung
Copy link
Member

This is probably basically the same as #2076 -- our diagnostics infrastructure was never tested for what happens when diagnostics are created in the "setup" phase of the interpreter, before any code runs. (We also have a tear-down phase after all code runs, which leads to issues like #2020.)

@saethlin
Copy link
Member

saethlin commented May 21, 2022

I tried and I can't reproduce this based on the report here 😕 I swear I've seen the referenced ICE before, and it's not obvious to me that any change has been made that should have fixed this.

@y86-dev
Copy link
Contributor Author

y86-dev commented May 21, 2022

Interesting, I also fail to reproduce this on the latest version...

@y86-dev
Copy link
Contributor Author

y86-dev commented May 21, 2022

hmm I did a quick git bisect and found 5a6c4a6 to be the responsible commit (only tested for 79). This seems strange, as it is only a version bump and a single line change in src/machine.rs. I do not know if that is the reason, but maybe something in rustc changed?

@RalfJung
Copy link
Member

This is the rustc range (assuming you always tested the version given in rust-version): rust-lang/rust@9a25164...8fbd92d.

I can't see anything obvious there, either... strange.

I am inclined to close this when #2076 is closed. We can always re-investigate if/when it happens again...

@RalfJung RalfJung closed this as completed Jun 5, 2022
@RalfJung
Copy link
Member

This might also have been caused by rust-lang/rust#87000, which I am working on fixing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants