diff --git a/cargo-miri/src/phases.rs b/cargo-miri/src/phases.rs index ca8b35a17b..b774ca8fa7 100644 --- a/cargo-miri/src/phases.rs +++ b/cargo-miri/src/phases.rs @@ -412,8 +412,11 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { // Arguments are treated very differently depending on whether this crate is // for interpretation by Miri, or for use by a build script / proc macro. if target_crate { - // Set the sysroot. - cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap()); + if phase != RustcPhase::Setup { + // Set the sysroot -- except during setup, where we don't have an existing sysroot yet + // and where the bootstrap wrapper adds its own `--sysroot` flag so we can't set ours. + cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap()); + } // Forward arguments, but patched. let emit_flag = "--emit"; @@ -578,9 +581,9 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner } if phase != RunnerPhase::Rustdoc { - // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot when invoking - // rustdoc itself, which will forward that flag when invoking rustc (i.e., us), so the flag - // is present in `info.args`. + // Set the sysroot. Not necessary in rustdoc, where we already set the sysroot in + // `phase_rustdoc`. rustdoc will forward that flag when invoking rustc (i.e., us), so the + // flag is present in `info.args`. cmd.arg("--sysroot").arg(env::var_os("MIRI_SYSROOT").unwrap()); } // Forward rustc arguments. diff --git a/rust-version b/rust-version index dfa7f8ca50..bd87405da3 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -63f70b3d104e20289a1a0df82747066c3d85b9a1 +803e33a4460c82581bd01d4008d0f44aef1ddfe8 diff --git a/src/borrow_tracker/mod.rs b/src/borrow_tracker/mod.rs index 8d76a48826..f21315790a 100644 --- a/src/borrow_tracker/mod.rs +++ b/src/borrow_tracker/mod.rs @@ -260,7 +260,7 @@ impl GlobalStateInner { &mut self, id: AllocId, alloc_size: Size, - kind: MemoryKind, + kind: MemoryKind, machine: &MiriMachine<'_, '_>, ) -> AllocState { match self.borrow_tracker_method { diff --git a/src/borrow_tracker/stacked_borrows/mod.rs b/src/borrow_tracker/stacked_borrows/mod.rs index 96ff298402..b4005515d9 100644 --- a/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/borrow_tracker/stacked_borrows/mod.rs @@ -509,7 +509,7 @@ impl Stacks { id: AllocId, size: Size, state: &mut GlobalStateInner, - kind: MemoryKind, + kind: MemoryKind, machine: &MiriMachine<'_, '_>, ) -> Self { let (base_tag, perm) = match kind { diff --git a/src/borrow_tracker/tree_borrows/mod.rs b/src/borrow_tracker/tree_borrows/mod.rs index a3d49756e4..492e324de4 100644 --- a/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/borrow_tracker/tree_borrows/mod.rs @@ -34,7 +34,7 @@ impl<'tcx> Tree { id: AllocId, size: Size, state: &mut GlobalStateInner, - _kind: MemoryKind, + _kind: MemoryKind, machine: &MiriMachine<'_, 'tcx>, ) -> Self { let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root diff --git a/src/concurrency/data_race.rs b/src/concurrency/data_race.rs index d51160b283..95049b91cb 100644 --- a/src/concurrency/data_race.rs +++ b/src/concurrency/data_race.rs @@ -844,7 +844,7 @@ impl VClockAlloc { global: &GlobalState, thread_mgr: &ThreadManager<'_, '_>, len: Size, - kind: MemoryKind, + kind: MemoryKind, current_span: Span, ) -> VClockAlloc { let (alloc_timestamp, alloc_index) = match kind { diff --git a/src/diagnostics.rs b/src/diagnostics.rs index dfbcaaac5c..d44d04e9bf 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -115,7 +115,7 @@ pub enum NonHaltingDiagnostic { /// This `Item` was popped from the borrow stack. The string explains the reason. PoppedPointerTag(Item, String), CreatedCallId(CallId), - CreatedAlloc(AllocId, Size, Align, MemoryKind), + CreatedAlloc(AllocId, Size, Align, MemoryKind), FreedAlloc(AllocId), AccessedAlloc(AllocId, AccessKind), RejectedIsolatedOp(String), @@ -447,7 +447,7 @@ pub fn report_error<'tcx, 'mir>( pub fn report_leaks<'mir, 'tcx>( ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>, - leaks: Vec<(AllocId, MemoryKind, Allocation>)>, + leaks: Vec<(AllocId, MemoryKind, Allocation>)>, ) { let mut any_pruned = false; for (id, kind, mut alloc) in leaks { diff --git a/src/lib.rs b/src/lib.rs index fbe4c9c676..2e19c9ff71 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -128,7 +128,7 @@ pub use crate::eval::{ }; pub use crate::helpers::{AccessKind, EvalContextExt as _}; pub use crate::machine::{ - AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, + AllocExtra, FrameExtra, MemoryKind, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, PrimitiveLayouts, Provenance, ProvenanceExtra, }; pub use crate::mono_hash_map::MonoHashMap; diff --git a/src/machine.rs b/src/machine.rs index ff081328a7..1d06d5c69d 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -135,9 +135,9 @@ pub enum MiriMemoryKind { Mmap, } -impl From for MemoryKind { +impl From for MemoryKind { #[inline(always)] - fn from(kind: MiriMemoryKind) -> MemoryKind { + fn from(kind: MiriMemoryKind) -> MemoryKind { MemoryKind::Machine(kind) } } @@ -185,6 +185,8 @@ impl fmt::Display for MiriMemoryKind { } } +pub type MemoryKind = interpret::MemoryKind; + /// Pointer provenance. #[derive(Clone, Copy)] pub enum Provenance { @@ -863,10 +865,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { type ProvenanceExtra = ProvenanceExtra; type Bytes = Box<[u8]>; - type MemoryMap = MonoHashMap< - AllocId, - (MemoryKind, Allocation), - >; + type MemoryMap = + MonoHashMap)>; const GLOBAL_KIND: Option = Some(MiriMemoryKind::Global); @@ -1088,7 +1088,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx: &MiriInterpCx<'mir, 'tcx>, id: AllocId, alloc: Cow<'b, Allocation>, - kind: Option>, + kind: Option, ) -> InterpResult<'tcx, Cow<'b, Allocation>> { let kind = kind.expect("we set our STATIC_KIND so this cannot be None"); if ecx.machine.tracked_alloc_ids.contains(&id) { @@ -1280,6 +1280,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), size: Size, align: Align, + _kind: MemoryKind, ) -> InterpResult<'tcx> { if machine.tracked_alloc_ids.contains(&alloc_id) { machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id)); diff --git a/src/shims/os_str.rs b/src/shims/os_str.rs index 0157c4845c..0409e31d65 100644 --- a/src/shims/os_str.rs +++ b/src/shims/os_str.rs @@ -137,7 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn alloc_os_str_as_c_str( &mut self, os_str: &OsStr, - memkind: MemoryKind, + memkind: MemoryKind, ) -> InterpResult<'tcx, Pointer>> { let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator. let this = self.eval_context_mut(); @@ -153,7 +153,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn alloc_os_str_as_wide_str( &mut self, os_str: &OsStr, - memkind: MemoryKind, + memkind: MemoryKind, ) -> InterpResult<'tcx, Pointer>> { let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator. let this = self.eval_context_mut(); @@ -230,7 +230,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn alloc_path_as_c_str( &mut self, path: &Path, - memkind: MemoryKind, + memkind: MemoryKind, ) -> InterpResult<'tcx, Pointer>> { let this = self.eval_context_mut(); let os_str = @@ -243,7 +243,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn alloc_path_as_wide_str( &mut self, path: &Path, - memkind: MemoryKind, + memkind: MemoryKind, ) -> InterpResult<'tcx, Pointer>> { let this = self.eval_context_mut(); let os_str = diff --git a/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr b/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr index 867907e98e..c26c7f397b 100644 --- a/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr +++ b/tests/fail/both_borrows/newtype_pair_retagging.stack.stderr @@ -6,7 +6,7 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) | = 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: was created by a Unique retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/newtype_pair_retagging.rs:LL:CC | LL | let ptr = Box::into_raw(Box::new(0i32)); diff --git a/tests/fail/both_borrows/newtype_retagging.stack.stderr b/tests/fail/both_borrows/newtype_retagging.stack.stderr index 56715938e9..ae54da70fe 100644 --- a/tests/fail/both_borrows/newtype_retagging.stack.stderr +++ b/tests/fail/both_borrows/newtype_retagging.stack.stderr @@ -6,7 +6,7 @@ LL | Box(unsafe { Unique::new_unchecked(raw) }, alloc) | = 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: was created by a Unique retag at offsets [0x0..0x4] +help: was created by a SharedReadWrite retag at offsets [0x0..0x4] --> $DIR/newtype_retagging.rs:LL:CC | LL | let ptr = Box::into_raw(Box::new(0i32)); diff --git a/tests/pass/issues/issue-miri-3473.rs b/tests/pass/issues/issue-miri-3473.rs new file mode 100644 index 0000000000..77b960c1cd --- /dev/null +++ b/tests/pass/issues/issue-miri-3473.rs @@ -0,0 +1,28 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows +use std::cell::UnsafeCell; + +#[repr(C)] +#[derive(Default)] +struct Node { + _meta: UnsafeCell, + value: usize, +} + +impl Node { + fn value(&self) -> &usize { + &self.value + } +} + +/// This used to cause Stacked Borrows errors because of trouble around conversion +/// from Box to raw pointer. +fn main() { + unsafe { + let a = Box::into_raw(Box::new(Node::default())); + let ptr = &*a; + *UnsafeCell::raw_get(a.cast::>()) = 2; + assert_eq!(*ptr.value(), 0); + drop(Box::from_raw(a)); + } +} diff --git a/tests/pass/stacked-borrows/stacked-borrows.rs b/tests/pass/stacked-borrows/stacked-borrows.rs index 734411ccc7..c75824d7f9 100644 --- a/tests/pass/stacked-borrows/stacked-borrows.rs +++ b/tests/pass/stacked-borrows/stacked-borrows.rs @@ -20,6 +20,7 @@ fn main() { wide_raw_ptr_in_tuple(); not_unpin_not_protected(); write_does_not_invalidate_all_aliases(); + box_into_raw_allows_interior_mutable_alias(); } // Make sure that reading from an `&mut` does, like reborrowing to `&`, @@ -263,3 +264,16 @@ fn write_does_not_invalidate_all_aliases() { other::lib2(); assert_eq!(*x, 1337); // oops, the value changed! I guess not all pointers were invalidated } + +fn box_into_raw_allows_interior_mutable_alias() { + unsafe { + let b = Box::new(std::cell::Cell::new(42)); + let raw = Box::into_raw(b); + let c = &*raw; + let d = raw.cast::(); // bypassing `Cell` -- only okay in Miri tests + // `c` and `d` should permit arbitrary aliasing with each other now. + *d = 1; + c.set(2); + drop(Box::from_raw(raw)); + } +}