diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 4a86490ed09a..279bf3d01d2e 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -101,14 +101,17 @@ impl<'mir, 'tcx> GlobalStateInner { } } - pub fn expose_addr(ecx: &MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId) { + pub fn expose_ptr(ecx: &mut MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId, sb: SbTag) { trace!("Exposing allocation id {:?}", alloc_id); - let mut global_state = ecx.machine.intptrcast.borrow_mut(); + let global_state = ecx.machine.intptrcast.get_mut(); // In legacy and strict mode, we don't need this, so we can save some cycles // by not tracking it. if global_state.provenance_mode == ProvenanceMode::Permissive { global_state.exposed.insert(alloc_id); + if ecx.machine.stacked_borrows.is_some() { + ecx.expose_tag(alloc_id, sb); + } } } diff --git a/src/machine.rs b/src/machine.rs index c2a7a34a9cc0..3704a5385141 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -489,6 +489,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { type AllocExtra = AllocExtra; type PointerTag = Tag; + // `None` represents a wildcard pointer. type TagExtra = Option; type MemoryMap = @@ -709,22 +710,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { ) -> InterpResult<'tcx> { match ptr.provenance { Tag::Concrete(ConcreteTag { alloc_id, sb }) => { - intptrcast::GlobalStateInner::expose_addr(ecx, alloc_id); - - let (size, _) = - ecx.get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead).unwrap(); - - // Function pointers and dead objects don't have an alloc_extra so we ignore them. - if let Ok(alloc_extra) = ecx.get_alloc_extra(alloc_id) { - if let Some(stacked_borrows) = &alloc_extra.stacked_borrows { - stacked_borrows.ptr_exposed( - alloc_id, - sb, - alloc_range(Size::from_bytes(0), size), - ecx.machine.stacked_borrows.as_ref().unwrap(), - )?; - } - } + intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, sb); } Tag::Wildcard => { // No need to do anything for wildcard pointers as diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index 75c2ff265879..b66864b8302a 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -117,7 +117,7 @@ pub struct Stacks { stacks: RefCell>, /// Stores past operations on this allocation history: RefCell, - /// The set of tags that have been exposed + /// The set of tags that have been exposed inside this allocation. exposed_tags: RefCell>, } @@ -708,26 +708,6 @@ impl Stacks { stacks } - #[inline(always)] - pub fn ptr_exposed<'tcx>( - &self, - alloc_id: AllocId, - tag: SbTag, - range: AllocRange, - _state: &GlobalState, - ) -> InterpResult<'tcx> { - trace!( - "allocation exposed with tag {:?}: {:?}, size {}", - tag, - Pointer::new(alloc_id, range.start), - range.size.bytes() - ); - - self.exposed_tags.borrow_mut().insert(tag); - - Ok(()) - } - #[inline(always)] pub fn memory_read<'tcx>( &self, @@ -1096,4 +1076,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx Ok(()) } + + /// Mark the given tag as exposed. It was found on a pointer with the given AllocId. + fn expose_tag(&mut self, alloc_id: AllocId, tag: SbTag) { + let this = self.eval_context_mut(); + + // Function pointers and dead objects don't have an alloc_extra so we ignore them. + // This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks. + // FIXME: this catches `InterpError`, which we should not usually do. + // We might need a proper fallible API from `memory.rs` to avoid this though. + if let Ok((alloc_extra, _)) = this.get_alloc_extra_mut(alloc_id) { + alloc_extra.stacked_borrows.as_mut().unwrap().exposed_tags.get_mut().insert(tag); + } + } }