@@ -168,11 +168,29 @@ impl fmt::Display for MiriMemoryKind {
168168/// Pointer provenance.
169169#[derive(Clone, Copy)]
170170pub enum Provenance {
171+ /// For pointers with concrete provenance. we exactly know which allocation they are attached to
172+ /// and what their borrow tag is.
171173 Concrete {
172174 alloc_id: AllocId,
173175 /// Borrow Tracker tag.
174176 tag: BorTag,
175177 },
178+ /// Pointers with wildcard provenance are created on int-to-ptr casts. According to the
179+ /// specification, we should at that point angelically "guess" a provenance that will make all
180+ /// future uses of this pointer work, if at all possible. Of course such a semantics cannot be
181+ /// actually implemented in Miri. So instead, we approximate this, erroring on the side of
182+ /// accepting too much code rather than rejecting correct code: a pointer with wildcard
183+ /// provenance "acts like" any previously exposed pointer. Each time it is used, we check
184+ /// whether *some* exposed pointer could have done what we want to do, and if the answer is yes
185+ /// then we allow the access. This allows too much code in two ways:
186+ /// - The same wildcard pointer can "take the role" of multiple different exposed pointers on
187+ /// subsequenct memory accesses.
188+ /// - In the aliasing model, we don't just have to know the borrow tag of the pointer used for
189+ /// the access, we also have to update the aliasing state -- and that update can be very
190+ /// different depending on which borrow tag we pick! Stacked Borrows has support for this by
191+ /// switching to a stack that is only approximately known, i.e. we overapproximate the effect
192+ /// of using *any* exposed pointer for this access, and only keep information about the borrow
193+ /// stack that would be true with all possible choices.
176194 Wildcard,
177195}
178196
@@ -1125,19 +1143,16 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11251143 _ => {}
11261144 }
11271145 }
1128- let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr)?;
11291146 let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker {
11301147 borrow_tracker.borrow_mut().base_ptr_tag(ptr.provenance, &ecx.machine)
11311148 } else {
11321149 // Value does not matter, SB is disabled
11331150 BorTag::default()
11341151 };
1135- Ok(Pointer::new(
1136- Provenance::Concrete { alloc_id: ptr.provenance, tag },
1137- Size::from_bytes(absolute_addr),
1138- ))
1152+ intptrcast::GlobalStateInner::ptr_from_rel_ptr(ecx, ptr, tag)
11391153 }
11401154
1155+ /// Called on `usize as ptr` casts.
11411156 #[inline(always)]
11421157 fn ptr_from_addr_cast(
11431158 ecx: &MiriInterpCx<'mir, 'tcx>,
@@ -1146,6 +1161,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11461161 intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr)
11471162 }
11481163
1164+ /// Called on `ptr as usize` casts.
1165+ /// (Actually computing the resulting `usize` doesn't need machine help,
1166+ /// that's just `Scalar::try_to_int`.)
11491167 fn expose_ptr(
11501168 ecx: &mut InterpCx<'mir, 'tcx, Self>,
11511169 ptr: Pointer<Self::Provenance>,
@@ -1163,11 +1181,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11631181
11641182 /// Convert a pointer with provenance into an allocation-offset pair,
11651183 /// or a `None` with an absolute address if that conversion is not possible.
1184+ ///
1185+ /// This is called when a pointer is about to be used for memory access,
1186+ /// an in-bounds check, or anything else that requires knowing which allocation it points to.
1187+ /// The resulting `AllocId` will just be used for that one step and the forgotten again
1188+ /// (i.e., we'll never turn the data returned here back into a `Pointer` that might be
1189+ /// stored in machine state).
11661190 fn ptr_get_alloc(
11671191 ecx: &MiriInterpCx<'mir, 'tcx>,
11681192 ptr: Pointer<Self::Provenance>,
11691193 ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
1170- let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel (ecx, ptr);
1194+ let rel = intptrcast::GlobalStateInner::ptr_get_alloc (ecx, ptr);
11711195
11721196 rel.map(|(alloc_id, size)| {
11731197 let tag = match ptr.provenance {
0 commit comments