diff --git a/rust-version b/rust-version index bd87405da3..f8f3016b15 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -803e33a4460c82581bd01d4008d0f44aef1ddfe8 +c45dee5efd0c042e9d1e24559ebd0d6424d8aa70 diff --git a/src/alloc_addresses/mod.rs b/src/alloc_addresses/mod.rs index fec39ec2b8..3e00e6037c 100644 --- a/src/alloc_addresses/mod.rs +++ b/src/alloc_addresses/mod.rs @@ -141,7 +141,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> { + fn addr_from_alloc_id(&self, alloc_id: AllocId, _kind: MemoryKind) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; @@ -283,16 +283,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } /// Convert a relative (tcx) pointer to a Miri pointer. - fn ptr_from_rel_ptr( + fn adjust_alloc_root_pointer( &self, ptr: Pointer, tag: BorTag, + kind: MemoryKind, ) -> InterpResult<'tcx, Pointer> { let ecx = self.eval_context_ref(); let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance) let alloc_id = prov.alloc_id(); - let base_addr = ecx.addr_from_alloc_id(alloc_id)?; + let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?; // Add offset with the right kind of pointer-overflowing arithmetic. let dl = ecx.data_layout(); @@ -314,9 +315,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ecx.alloc_id_from_addr(addr.bytes())? }; - // This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr + // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer // must have been called in the past, so we can just look up the address in the map. - let base_addr = ecx.addr_from_alloc_id(alloc_id).unwrap(); + let base_addr = *ecx.machine.alloc_addresses.borrow().base_addr.get(&alloc_id).unwrap(); // Wrapping "addr - base_addr" #[allow(clippy::cast_possible_wrap)] // we want to wrap here diff --git a/src/borrow_tracker/mod.rs b/src/borrow_tracker/mod.rs index f21315790a..24e2a9a74b 100644 --- a/src/borrow_tracker/mod.rs +++ b/src/borrow_tracker/mod.rs @@ -89,10 +89,10 @@ pub struct GlobalStateInner { borrow_tracker_method: BorrowTrackerMethod, /// Next unused pointer ID (tag). next_ptr_tag: BorTag, - /// Table storing the "base" tag for each allocation. - /// The base tag is the one used for the initial pointer. + /// Table storing the "root" tag for each allocation. + /// The root tag is the one used for the initial pointer. /// We need this in a separate table to handle cyclic statics. - base_ptr_tags: FxHashMap, + root_ptr_tags: FxHashMap, /// Next unused call ID (for protectors). next_call_id: CallId, /// All currently protected tags. @@ -175,7 +175,7 @@ impl GlobalStateInner { GlobalStateInner { borrow_tracker_method, next_ptr_tag: BorTag::one(), - base_ptr_tags: FxHashMap::default(), + root_ptr_tags: FxHashMap::default(), next_call_id: NonZero::new(1).unwrap(), protected_tags: FxHashMap::default(), tracked_pointer_tags, @@ -213,8 +213,8 @@ impl GlobalStateInner { } } - pub fn base_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_, '_>) -> BorTag { - self.base_ptr_tags.get(&id).copied().unwrap_or_else(|| { + pub fn root_ptr_tag(&mut self, id: AllocId, machine: &MiriMachine<'_, '_>) -> BorTag { + self.root_ptr_tags.get(&id).copied().unwrap_or_else(|| { let tag = self.new_ptr(); if self.tracked_pointer_tags.contains(&tag) { machine.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag( @@ -223,14 +223,14 @@ impl GlobalStateInner { None, )); } - trace!("New allocation {:?} has base tag {:?}", id, tag); - self.base_ptr_tags.try_insert(id, tag).unwrap(); + trace!("New allocation {:?} has rpot tag {:?}", id, tag); + self.root_ptr_tags.try_insert(id, tag).unwrap(); tag }) } pub fn remove_unreachable_allocs(&mut self, allocs: &LiveAllocs<'_, '_, '_>) { - self.base_ptr_tags.retain(|id, _| allocs.is_live(*id)); + self.root_ptr_tags.retain(|id, _| allocs.is_live(*id)); } } diff --git a/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/borrow_tracker/stacked_borrows/diagnostics.rs index 5a941ae9d0..cb677b8653 100644 --- a/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -20,7 +20,7 @@ fn err_sb_ub<'tcx>( #[derive(Clone, Debug)] pub struct AllocHistory { id: AllocId, - base: (Item, Span), + root: (Item, Span), creations: smallvec::SmallVec<[Creation; 1]>, invalidations: smallvec::SmallVec<[Invalidation; 1]>, protectors: smallvec::SmallVec<[Protection; 1]>, @@ -225,7 +225,7 @@ impl AllocHistory { pub fn new(id: AllocId, item: Item, machine: &MiriMachine<'_, '_>) -> Self { Self { id, - base: (item, machine.current_span()), + root: (item, machine.current_span()), creations: SmallVec::new(), invalidations: SmallVec::new(), protectors: SmallVec::new(), @@ -342,15 +342,15 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> { }) }) .or_else(|| { - // If we didn't find a retag that created this tag, it might be the base tag of + // If we didn't find a retag that created this tag, it might be the root tag of // this allocation. - if self.history.base.0.tag() == tag { + if self.history.root.0.tag() == tag { Some(( format!( - "{tag:?} was created here, as the base tag for {:?}", + "{tag:?} was created here, as the root tag for {:?}", self.history.id ), - self.history.base.1.data(), + self.history.root.1.data(), )) } else { None diff --git a/src/borrow_tracker/stacked_borrows/mod.rs b/src/borrow_tracker/stacked_borrows/mod.rs index b4005515d9..a6dd1d829c 100644 --- a/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/borrow_tracker/stacked_borrows/mod.rs @@ -518,9 +518,9 @@ impl Stacks { // not through a pointer). That is, whenever we directly write to a local, this will pop // everything else off the stack, invalidating all previous pointers, // and in particular, *all* raw pointers. - MemoryKind::Stack => (state.base_ptr_tag(id, machine), Permission::Unique), + MemoryKind::Stack => (state.root_ptr_tag(id, machine), Permission::Unique), // Everything else is shared by default. - _ => (state.base_ptr_tag(id, machine), Permission::SharedReadWrite), + _ => (state.root_ptr_tag(id, machine), Permission::SharedReadWrite), }; Stacks::new(size, perm, base_tag, id, machine) } diff --git a/src/borrow_tracker/stacked_borrows/stack.rs b/src/borrow_tracker/stacked_borrows/stack.rs index 76430498e2..bebd14d2f1 100644 --- a/src/borrow_tracker/stacked_borrows/stack.rs +++ b/src/borrow_tracker/stacked_borrows/stack.rs @@ -47,7 +47,7 @@ impl Stack { let mut first_removed = None; // We never consider removing the bottom-most tag. For stacks without an unknown - // bottom this preserves the base tag. + // bottom this preserves the root tag. // Note that the algorithm below is based on considering the tag at read_idx - 1, // so precisely considering the tag at index 0 for removal when we have an unknown // bottom would complicate the implementation. The simplification of not considering @@ -93,7 +93,7 @@ impl Stack { self.unique_range = 0..self.len(); } - // Replace any Items which have been collected with the base item, a known-good value. + // Replace any Items which have been collected with the root item, a known-good value. for i in 0..CACHE_LEN { if self.cache.idx[i] >= first_removed { self.cache.items[i] = self.borrows[0]; @@ -331,7 +331,7 @@ impl<'tcx> Stack { self.verify_cache_consistency(); } - /// Construct a new `Stack` using the passed `Item` as the base tag. + /// Construct a new `Stack` using the passed `Item` as the root tag. pub fn new(item: Item) -> Self { Stack { borrows: vec![item], @@ -438,8 +438,8 @@ impl<'tcx> Stack { let mut removed = 0; let mut cursor = 0; // Remove invalid entries from the cache by rotating them to the end of the cache, then - // keep track of how many invalid elements there are and overwrite them with the base tag. - // The base tag here serves as a harmless default value. + // keep track of how many invalid elements there are and overwrite them with the root tag. + // The root tag here serves as a harmless default value. for _ in 0..CACHE_LEN - 1 { if self.cache.idx[cursor] >= start { self.cache.idx[cursor..CACHE_LEN - removed].rotate_left(1); diff --git a/src/borrow_tracker/tree_borrows/mod.rs b/src/borrow_tracker/tree_borrows/mod.rs index 492e324de4..fc5eb942a2 100644 --- a/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/borrow_tracker/tree_borrows/mod.rs @@ -37,7 +37,7 @@ impl<'tcx> Tree { _kind: MemoryKind, machine: &MiriMachine<'_, 'tcx>, ) -> Self { - let tag = state.base_ptr_tag(id, machine); // Fresh tag for the root + let tag = state.root_ptr_tag(id, machine); // Fresh tag for the root let span = machine.current_span(); Tree::new(tag, size, span) } diff --git a/src/machine.rs b/src/machine.rs index 1d06d5c69d..0bfc59e67d 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -503,7 +503,7 @@ pub struct MiriMachine<'mir, 'tcx> { /// Crates which are considered local for the purposes of error reporting. pub(crate) local_crates: Vec, - /// Mapping extern static names to their base pointer. + /// Mapping extern static names to their pointer. extern_statics: FxHashMap>, /// The random number generator used for resolving non-determinism. @@ -1042,14 +1042,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { ecx.generate_nan(inputs) } - fn thread_local_static_base_pointer( + fn thread_local_static_pointer( ecx: &mut MiriInterpCx<'mir, 'tcx>, def_id: DefId, ) -> InterpResult<'tcx, Pointer> { ecx.get_or_create_thread_local_alloc(def_id) } - fn extern_static_base_pointer( + fn extern_static_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, def_id: DefId, ) -> InterpResult<'tcx, Pointer> { @@ -1090,7 +1090,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { alloc: Cow<'b, Allocation>, kind: Option, ) -> InterpResult<'tcx, Cow<'b, Allocation>> { - let kind = kind.expect("we set our STATIC_KIND so this cannot be None"); + let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None"); if ecx.machine.tracked_alloc_ids.contains(&id) { ecx.emit_diagnostic(NonHaltingDiagnostic::CreatedAlloc( id, @@ -1135,7 +1135,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { weak_memory: buffer_alloc, backtrace, }, - |ptr| ecx.global_base_pointer(ptr), + |ptr| ecx.global_root_pointer(ptr), )?; if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) { @@ -1148,31 +1148,33 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { Ok(Cow::Owned(alloc)) } - fn adjust_alloc_base_pointer( + fn adjust_alloc_root_pointer( ecx: &MiriInterpCx<'mir, 'tcx>, ptr: Pointer, + kind: Option, ) -> InterpResult<'tcx, Pointer> { + let kind = kind.expect("we set our GLOBAL_KIND so this cannot be None"); let alloc_id = ptr.provenance.alloc_id(); if cfg!(debug_assertions) { // The machine promises to never call us on thread-local or extern statics. match ecx.tcx.try_get_global_alloc(alloc_id) { Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_thread_local_static(def_id) => { - panic!("adjust_alloc_base_pointer called on thread-local static") + panic!("adjust_alloc_root_pointer called on thread-local static") } Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_foreign_item(def_id) => { - panic!("adjust_alloc_base_pointer called on extern static") + panic!("adjust_alloc_root_pointer called on extern static") } _ => {} } } // FIXME: can we somehow preserve the immutability of `ptr`? let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker { - borrow_tracker.borrow_mut().base_ptr_tag(alloc_id, &ecx.machine) + borrow_tracker.borrow_mut().root_ptr_tag(alloc_id, &ecx.machine) } else { // Value does not matter, SB is disabled BorTag::default() }; - ecx.ptr_from_rel_ptr(ptr, tag) + ecx.adjust_alloc_root_pointer(ptr, tag, kind) } /// Called on `usize as ptr` casts. diff --git a/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr b/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr index f6eeef33e9..8426f56004 100644 --- a/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr +++ b/tests/fail/both_borrows/invalidate_against_protector3.stack.stderr @@ -6,7 +6,7 @@ LL | unsafe { *x = 0 }; | = 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 here, as the base tag for ALLOC +help: was created here, as the root tag for ALLOC --> $DIR/invalidate_against_protector3.rs:LL:CC | LL | let ptr = alloc(Layout::for_value(&0i32)) as *mut i32;