Skip to content

Commit 2413da5

Browse files
committed
interpret: simplify pointer arithmetic logic
1 parent 34d25b0 commit 2413da5

15 files changed

+40
-58
lines changed

src/alloc_addresses/mod.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rand::Rng;
1111

1212
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1313
use rustc_span::Span;
14-
use rustc_target::abi::{Align, HasDataLayout, Size};
14+
use rustc_target::abi::{Align, Size};
1515

1616
use crate::{concurrency::VClock, *};
1717

@@ -307,15 +307,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
307307

308308
let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
309309
let alloc_id = prov.alloc_id();
310-
let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?;
311310

312-
// Add offset with the right kind of pointer-overflowing arithmetic.
313-
let dl = ecx.data_layout();
314-
let absolute_addr = dl.overflowing_offset(base_addr, offset.bytes()).0;
315-
Ok(interpret::Pointer::new(
311+
// Get a pointer to the beginning of this allocation.
312+
let base_addr = ecx.addr_from_alloc_id(alloc_id, kind)?;
313+
let base_ptr = interpret::Pointer::new(
316314
Provenance::Concrete { alloc_id, tag },
317-
Size::from_bytes(absolute_addr),
318-
))
315+
Size::from_bytes(base_addr),
316+
);
317+
// Add offset with the right kind of pointer-overflowing arithmetic.
318+
Ok(base_ptr.wrapping_offset(offset, ecx))
319319
}
320320

321321
/// When a pointer is used for a memory access, this computes where in which allocation the
@@ -341,12 +341,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
341341
let base_addr = *ecx.machine.alloc_addresses.borrow().base_addr.get(&alloc_id).unwrap();
342342

343343
// Wrapping "addr - base_addr"
344-
#[allow(clippy::cast_possible_wrap)] // we want to wrap here
345-
let neg_base_addr = (base_addr as i64).wrapping_neg();
346-
Some((
347-
alloc_id,
348-
Size::from_bytes(ecx.overflowing_signed_offset(addr.bytes(), neg_base_addr).0),
349-
))
344+
let rel_offset = ecx.truncate_to_target_usize(addr.bytes().wrapping_sub(base_addr));
345+
Some((alloc_id, Size::from_bytes(rel_offset)))
350346
}
351347
}
352348

src/helpers.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
606606
}
607607
// The part between the end_ptr and the end of the place is also frozen.
608608
// So pretend there is a 0-sized `UnsafeCell` at the end.
609-
unsafe_cell_action(&place.ptr().offset(size, this)?, Size::ZERO)?;
609+
unsafe_cell_action(&place.ptr().wrapping_offset(size, this), Size::ZERO)?;
610610
// Done!
611611
return Ok(());
612612

@@ -975,7 +975,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
975975
loop {
976976
// FIXME: We are re-getting the allocation each time around the loop.
977977
// Would be nice if we could somehow "extend" an existing AllocRange.
978-
let alloc = this.get_ptr_alloc(ptr.offset(len, this)?, size1)?.unwrap(); // not a ZST, so we will get a result
978+
let alloc = this.get_ptr_alloc(ptr.wrapping_offset(len, this), size1)?.unwrap(); // not a ZST, so we will get a result
979979
let byte = alloc.read_integer(alloc_range(Size::ZERO, size1))?.to_u8()?;
980980
if byte == 0 {
981981
break;
@@ -1039,7 +1039,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10391039
break;
10401040
} else {
10411041
wchars.push(wchar_int.try_into().unwrap());
1042-
ptr = ptr.offset(size, this)?;
1042+
ptr = ptr.wrapping_offset(size, this);
10431043
}
10441044
}
10451045

src/shims/foreign_items.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
622622
{
623623
let idx = u64::try_from(idx).unwrap();
624624
#[allow(clippy::arithmetic_side_effects)] // idx < num, so this never wraps
625-
let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?;
625+
let new_ptr = ptr.wrapping_offset(Size::from_bytes(num - idx - 1), this);
626626
this.write_pointer(new_ptr, dest)?;
627627
} else {
628628
this.write_null(dest)?;
@@ -646,7 +646,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
646646
.iter()
647647
.position(|&c| c == val);
648648
if let Some(idx) = idx {
649-
let new_ptr = ptr.offset(Size::from_bytes(idx as u64), this)?;
649+
let new_ptr = ptr.wrapping_offset(Size::from_bytes(idx as u64), this);
650650
this.write_pointer(new_ptr, dest)?;
651651
} else {
652652
this.write_null(dest)?;

src/shims/unix/env.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<'tcx> UnixEnvVars<'tcx> {
8282
};
8383
// The offset is used to strip the "{name}=" part of the string.
8484
let var_ptr = var_ptr
85-
.offset(Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), ecx)?;
85+
.wrapping_offset(Size::from_bytes(u64::try_from(name.len()).unwrap().strict_add(1)), ecx);
8686
Ok(Some(var_ptr))
8787
}
8888

src/shims/unix/fs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -996,7 +996,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
996996
&this.ptr_to_mplace(entry, dirent64_layout),
997997
)?;
998998

999-
let name_ptr = entry.offset(Size::from_bytes(d_name_offset), this)?;
999+
let name_ptr = entry.wrapping_offset(Size::from_bytes(d_name_offset), this);
10001000
this.write_bytes_ptr(name_ptr, name_bytes.iter().copied())?;
10011001

10021002
Some(entry)

src/shims/unix/linux/mem.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
5353
// We just allocated this, the access is definitely in-bounds and fits into our address space.
5454
// mmap guarantees new mappings are zero-init.
5555
this.write_bytes_ptr(
56-
ptr.offset(Size::from_bytes(old_size), this).unwrap().into(),
56+
ptr.wrapping_offset(Size::from_bytes(old_size), this).into(),
5757
std::iter::repeat(0u8).take(usize::try_from(increase).unwrap()),
5858
)
5959
.unwrap();

tests/fail/intrinsics/out_of_bounds_ptr_2.rs

Lines changed: 0 additions & 6 deletions
This file was deleted.

tests/fail/intrinsics/out_of_bounds_ptr_2.stderr

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/fail/intrinsics/ptr_offset_int_plus_ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//@compile-flags: -Zmiri-permissive-provenance
2-
//@normalize-stderr-test: "to \d+ bytes of memory" -> "to $$BYTES bytes of memory"
2+
//@normalize-stderr-test: "\d+ bytes" -> "$$BYTES bytes"
33

44
fn main() {
55
let ptr = Box::into_raw(Box::new(0u32));
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
fn main() {
22
let v = [0i8; 4];
33
let x = &v as *const i8;
4-
// The error is inside another function, so we cannot match it by line
54
let x = unsafe { x.offset(5) }; //~ERROR: expected a pointer to 5 bytes of memory
65
panic!("this should never print: {:?}", x);
76
}

0 commit comments

Comments
 (0)