Skip to content

Commit 1ee055f

Browse files
committed
add some comments and some cleanup around Miri intptrcast
1 parent 3c23df4 commit 1ee055f

File tree

3 files changed

+40
-25
lines changed

3 files changed

+40
-25
lines changed

compiler/rustc_const_eval/src/interpret/memory.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
12491249

12501250
/// Turning a "maybe pointer" into a proper pointer (and some information
12511251
/// about where it points), or an absolute address.
1252+
///
1253+
/// The result must be used immediately; it is not allowed to convert
1254+
/// the returned data back into a `Pointer` and store that in machine state.
1255+
/// (In fact that's not even possible since `M::ProvenanceExtra` is generic and
1256+
/// we don't have an operation to turn it back into `M::Provenance`.)
12521257
pub fn ptr_try_get_alloc_id(
12531258
&self,
12541259
ptr: Pointer<Option<M::Provenance>>,
@@ -1267,6 +1272,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
12671272
}
12681273

12691274
/// Turning a "maybe pointer" into a proper pointer (and some information about where it points).
1275+
///
1276+
/// The result must be used immediately; it is not allowed to convert
1277+
/// the returned data back into a `Pointer` and store that in machine state.
1278+
/// (In fact that's not even possible since `M::ProvenanceExtra` is generic and
1279+
/// we don't have an operation to turn it back into `M::Provenance`.)
12701280
#[inline(always)]
12711281
pub fn ptr_get_alloc_id(
12721282
&self,

src/tools/miri/src/intptrcast.rs

+18-19
Original file line numberDiff line numberDiff line change
@@ -119,24 +119,14 @@ impl<'mir, 'tcx> GlobalStateInner {
119119
Ok(())
120120
}
121121

122-
pub fn ptr_from_addr_transmute(
123-
_ecx: &MiriInterpCx<'mir, 'tcx>,
124-
addr: u64,
125-
) -> Pointer<Option<Provenance>> {
126-
trace!("Transmuting {:#x} to a pointer", addr);
127-
128-
// We consider transmuted pointers to be "invalid" (`None` provenance).
129-
Pointer::new(None, Size::from_bytes(addr))
130-
}
131-
132122
pub fn ptr_from_addr_cast(
133123
ecx: &MiriInterpCx<'mir, 'tcx>,
134124
addr: u64,
135125
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
136126
trace!("Casting {:#x} to a pointer", addr);
137127

128+
// Potentially emit a warning.
138129
let global_state = ecx.machine.intptrcast.borrow();
139-
140130
match global_state.provenance_mode {
141131
ProvenanceMode::Default => {
142132
// The first time this happens at a particular location, print a warning.
@@ -158,7 +148,12 @@ impl<'mir, 'tcx> GlobalStateInner {
158148
ProvenanceMode::Permissive => {}
159149
}
160150

161-
// This is how wildcard pointers are born.
151+
// We do *not* look up the `AllocId` here! This is a `ptr as usize` cast, and it is
152+
// completely legal to do a cast and then `wrapping_offset` to another allocation and only
153+
// *then* do a memory access. So the allocation that the pointer happens to point to on a
154+
// cast is fairly irrelevant. Instead we generate this as a "wildcard" pointer, such that
155+
// *every time the pointer is used*, we do an `AllocId` lookup to find the (exposed)
156+
// allocation it might be referencing.
162157
Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr)))
163158
}
164159

@@ -219,22 +214,27 @@ impl<'mir, 'tcx> GlobalStateInner {
219214
})
220215
}
221216

222-
/// Convert a relative (tcx) pointer to an absolute address.
223-
pub fn rel_ptr_to_addr(
217+
/// Convert a relative (tcx) pointer to a Miri pointer.
218+
pub fn ptr_from_rel_ptr(
224219
ecx: &MiriInterpCx<'mir, 'tcx>,
225220
ptr: Pointer<AllocId>,
226-
) -> InterpResult<'tcx, u64> {
221+
tag: BorTag,
222+
) -> InterpResult<'tcx, Pointer<Provenance>> {
227223
let (alloc_id, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
228224
let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id)?;
229225

230226
// Add offset with the right kind of pointer-overflowing arithmetic.
231227
let dl = ecx.data_layout();
232-
Ok(dl.overflowing_offset(base_addr, offset.bytes()).0)
228+
let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0;
229+
Ok(Pointer::new(
230+
Provenance::Concrete { alloc_id, tag },
231+
Size::from_bytes(absolute_addr),
232+
))
233233
}
234234

235235
/// When a pointer is used for a memory access, this computes where in which allocation the
236236
/// access is going.
237-
pub fn abs_ptr_to_rel(
237+
pub fn ptr_get_alloc(
238238
ecx: &MiriInterpCx<'mir, 'tcx>,
239239
ptr: Pointer<Provenance>,
240240
) -> Option<(AllocId, Size)> {
@@ -252,12 +252,11 @@ impl<'mir, 'tcx> GlobalStateInner {
252252
let base_addr = GlobalStateInner::alloc_base_addr(ecx, alloc_id).unwrap();
253253

254254
// Wrapping "addr - base_addr"
255-
let dl = ecx.data_layout();
256255
#[allow(clippy::cast_possible_wrap)] // we want to wrap here
257256
let neg_base_addr = (base_addr as i64).wrapping_neg();
258257
Some((
259258
alloc_id,
260-
Size::from_bytes(dl.overflowing_signed_offset(addr.bytes(), neg_base_addr).0),
259+
Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0),
261260
))
262261
}
263262

src/tools/miri/src/machine.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -1136,19 +1136,16 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11361136
_ => {}
11371137
}
11381138
}
1139-
let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr)?;
11401139
let tag = if let Some(borrow_tracker) = &ecx.machine.borrow_tracker {
11411140
borrow_tracker.borrow_mut().base_ptr_tag(ptr.provenance, &ecx.machine)
11421141
} else {
11431142
// Value does not matter, SB is disabled
11441143
BorTag::default()
11451144
};
1146-
Ok(Pointer::new(
1147-
Provenance::Concrete { alloc_id: ptr.provenance, tag },
1148-
Size::from_bytes(absolute_addr),
1149-
))
1145+
intptrcast::GlobalStateInner::ptr_from_rel_ptr(ecx, ptr, tag)
11501146
}
11511147

1148+
/// Called on `usize as ptr` casts.
11521149
#[inline(always)]
11531150
fn ptr_from_addr_cast(
11541151
ecx: &MiriInterpCx<'mir, 'tcx>,
@@ -1157,6 +1154,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11571154
intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr)
11581155
}
11591156

1157+
/// Called on `ptr as usize` casts.
1158+
/// (Actually computing the resulting `usize` doesn't need machine help,
1159+
/// that's just `Scalar::try_to_int`.)
11601160
fn expose_ptr(
11611161
ecx: &mut InterpCx<'mir, 'tcx, Self>,
11621162
ptr: Pointer<Self::Provenance>,
@@ -1174,11 +1174,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
11741174

11751175
/// Convert a pointer with provenance into an allocation-offset pair,
11761176
/// or a `None` with an absolute address if that conversion is not possible.
1177+
///
1178+
/// This is called when a pointer is about to be used for memory access,
1179+
/// an in-bounds check, or anything else that requires knowing which allocation it points to.
1180+
/// The resulting `AllocId` will just be used for that one step and the forgotten again
1181+
/// (i.e., we'll never turn the data returned here back into a `Pointer` that might be
1182+
/// stored in machine state).
11771183
fn ptr_get_alloc(
11781184
ecx: &MiriInterpCx<'mir, 'tcx>,
11791185
ptr: Pointer<Self::Provenance>,
11801186
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
1181-
let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel(ecx, ptr);
1187+
let rel = intptrcast::GlobalStateInner::ptr_get_alloc(ecx, ptr);
11821188

11831189
rel.map(|(alloc_id, size)| {
11841190
let tag = match ptr.provenance {

0 commit comments

Comments
 (0)