- // This never overflows because `int >= glb`
- let offset = int - glb;
- // If the offset exceeds the size of the allocation, this access is illegal
- if offset <= memory.get_size_and_align(alloc_id, AllocCheck::MaybeDead)?.0.bytes() {
- // This pointer is untagged because it was created from a cast
- Pointer::new_with_tag(alloc_id, Size::from_bytes(offset), Tag::Untagged)
- } else {
- throw_ub!(InvalidIntPointerUsage(int))
+ // This never overflows because `addr >= glb`
+ let offset = addr - glb;
+ // If the offset exceeds the size of the allocation, don't use this `alloc_id`.
+ let size = ecx.get_alloc_info(alloc_id).0;
+ if offset <= size.bytes() { Some(alloc_id) } else { None }
+ }
+ }?;
+
+ // We only use this provenance if it has been exposed, *and* is still live.
+ if global_state.exposed.contains(&alloc_id) {
+ let (_size, _align, kind) = ecx.get_alloc_info(alloc_id);
+ match kind {
+ AllocKind::LiveData | AllocKind::Function => return Some(alloc_id),
+ AllocKind::Dead => {}
+ }
+ }
+
+ None
+ }
+
+ pub fn expose_ptr(ecx: &mut MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId, sb: SbTag) {
+ let global_state = ecx.machine.intptrcast.get_mut();
+ // In strict mode, we don't need this, so we can save some cycles by not tracking it.
+ if global_state.provenance_mode != ProvenanceMode::Strict {
+ trace!("Exposing allocation id {alloc_id:?}");
+ global_state.exposed.insert(alloc_id);
+ if ecx.machine.stacked_borrows.is_some() {
+ ecx.expose_tag(alloc_id, sb);
+ }
+ }
+ }
+
+ pub fn ptr_from_addr_transmute(
+ ecx: &MiriEvalContext<'mir, 'tcx>,
+ addr: u64,
+ ) -> Pointer<Option<Tag>> {
+ trace!("Transmuting 0x{:x} to a pointer", addr);
+
+ let provenance = if ecx.machine.allow_ptr_int_transmute {
+ // When we allow transmutes, treat them like casts: generating a wildcard pointer.
+ Some(Tag::Wildcard)
+ } else {
+ // Usually, we consider transmuted pointers to be "invalid" (`None` provenance).
+ None
+ };
+ Pointer::new(provenance, Size::from_bytes(addr))
+ }
+
+ pub fn ptr_from_addr_cast(
+ ecx: &MiriEvalContext<'mir, 'tcx>,
+ addr: u64,
+ ) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
+ trace!("Casting 0x{:x} to a pointer", addr);
+
+ let global_state = ecx.machine.intptrcast.borrow();
+
+ match global_state.provenance_mode {
+ ProvenanceMode::Default => {
+ // The first time this happens at a particular location, print a warning.
+ thread_local! {
+ // `Span` is non-`Send`, so we use a thread-local instead.
+ static PAST_WARNINGS: RefCell<FxHashSet<Span>> = RefCell::default();