diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 8395cdc273..4850945b4e 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -105,6 +105,8 @@ impl<'mir, 'tcx> GlobalStateInner { trace!("Exposing allocation id {:?}", alloc_id); let mut global_state = ecx.machine.intptrcast.borrow_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); } @@ -118,12 +120,17 @@ impl<'mir, 'tcx> GlobalStateInner { let global_state = ecx.machine.intptrcast.borrow(); - // In legacy mode, we have to support int2ptr transmutes, - // so just pretend they do the same thing as a cast. - if global_state.provenance_mode == ProvenanceMode::Legacy { - Self::ptr_from_addr_cast(ecx, addr) - } else { - Pointer::new(None, Size::from_bytes(addr)) + match global_state.provenance_mode { + ProvenanceMode::Legacy => { + // In legacy mode, we have to support int2ptr transmutes, + // so just pretend they do the same thing as a cast. + Self::ptr_from_addr_cast(ecx, addr) + } + ProvenanceMode::Permissive | ProvenanceMode::Strict => { + // Both of these modes consider transmuted pointers to be "invalid" (`None` + // provenance). + Pointer::new(None, Size::from_bytes(addr)) + } } } @@ -135,18 +142,26 @@ impl<'mir, 'tcx> GlobalStateInner { let global_state = ecx.machine.intptrcast.borrow(); - if global_state.provenance_mode == ProvenanceMode::Strict { - Pointer::new(None, Size::from_bytes(addr)) - } else if global_state.provenance_mode == ProvenanceMode::Legacy { - let alloc_id = Self::alloc_id_from_addr(ecx, addr); - - Pointer::new( - alloc_id - .map(|alloc_id| Tag::Concrete(ConcreteTag { alloc_id, sb: SbTag::Untagged })), - Size::from_bytes(addr), - ) - } else { - Pointer::new(Some(Tag::Wildcard), Size::from_bytes(addr)) + match global_state.provenance_mode { + ProvenanceMode::Legacy => { + // Determine the allocation this points to at cast time. + let alloc_id = Self::alloc_id_from_addr(ecx, addr); + Pointer::new( + alloc_id.map(|alloc_id| { + Tag::Concrete(ConcreteTag { alloc_id, sb: SbTag::Untagged }) + }), + Size::from_bytes(addr), + ) + } + ProvenanceMode::Strict => { + // We don't support int2ptr casts in this mode (i.e., we treat them like + // transmutes). + Pointer::new(None, Size::from_bytes(addr)) + } + ProvenanceMode::Permissive => { + // This is how wildcard pointers are born. + Pointer::new(Some(Tag::Wildcard), Size::from_bytes(addr)) + } } } @@ -215,6 +230,8 @@ impl<'mir, 'tcx> GlobalStateInner { let alloc_id = if let Tag::Concrete(concrete) = tag { concrete.alloc_id } else { + // A wildcard pointer. + assert_eq!(ecx.machine.intptrcast.borrow().provenance_mode, ProvenanceMode::Permissive); GlobalStateInner::alloc_id_from_addr(ecx, addr.bytes())? }; diff --git a/src/machine.rs b/src/machine.rs index 12a32d81b5..0972699e72 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -652,19 +652,18 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { intptrcast::GlobalStateInner::ptr_from_addr_transmute(ecx, addr) } - #[inline(always)] fn expose_ptr( ecx: &mut InterpCx<'mir, 'tcx, Self>, ptr: Pointer, ) -> InterpResult<'tcx> { - let tag = ptr.provenance; - - if let Tag::Concrete(concrete) = tag { - intptrcast::GlobalStateInner::expose_addr(ecx, concrete.alloc_id); + match ptr.provenance { + Tag::Concrete(concrete) => + intptrcast::GlobalStateInner::expose_addr(ecx, concrete.alloc_id), + Tag::Wildcard => { + // No need to do anything for wildcard pointers as + // their provenances have already been previously exposed. + } } - - // No need to do anything for wildcard pointers as - // their provenances have already been previously exposed. Ok(()) } @@ -676,12 +675,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> { ) -> Option<(AllocId, Size, Self::TagExtra)> { let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel(ecx, ptr); - let sb = match ptr.provenance { - Tag::Concrete(ConcreteTag { sb, .. }) => sb, - Tag::Wildcard => SbTag::Untagged, - }; - - rel.map(|(alloc_id, size)| (alloc_id, size, sb)) + rel.map(|(alloc_id, size)| { + let sb = match ptr.provenance { + Tag::Concrete(ConcreteTag { sb, .. }) => sb, + Tag::Wildcard => SbTag::Untagged, + }; + (alloc_id, size, sb) + }) } #[inline(always)]