properly wrap pointer offsets at pointer size
This commit is contained in:
@@ -60,11 +60,11 @@ impl Pointer {
|
||||
Pointer { alloc_id, offset }
|
||||
}
|
||||
|
||||
pub fn wrapping_signed_offset<'tcx>(self, i: i64) -> Self {
|
||||
Pointer::new(self.alloc_id, self.offset.wrapping_add(i as u64))
|
||||
pub fn wrapping_signed_offset<'tcx>(self, i: i64, layout: &TargetDataLayout) -> Self {
|
||||
Pointer::new(self.alloc_id, (self.offset.wrapping_add(i as u64) as u128 % (1u128 << layout.pointer_size.bits())) as u64)
|
||||
}
|
||||
|
||||
pub fn signed_offset<'tcx>(self, i: i64) -> EvalResult<'tcx, Self> {
|
||||
pub fn signed_offset<'tcx>(self, i: i64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
// FIXME: is it possible to over/underflow here?
|
||||
if i < 0 {
|
||||
// trickery to ensure that i64::min_value() works fine
|
||||
@@ -76,13 +76,17 @@ impl Pointer {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
}
|
||||
} else {
|
||||
self.offset(i as u64)
|
||||
self.offset(i as u64, layout)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset<'tcx>(self, i: u64) -> EvalResult<'tcx, Self> {
|
||||
pub fn offset<'tcx>(self, i: u64, layout: &TargetDataLayout) -> EvalResult<'tcx, Self> {
|
||||
if let Some(res) = self.offset.checked_add(i) {
|
||||
Ok(Pointer::new(self.alloc_id, res))
|
||||
if res as u128 >= (1u128 << layout.pointer_size.bits()) {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
} else {
|
||||
Ok(Pointer::new(self.alloc_id, res))
|
||||
}
|
||||
} else {
|
||||
Err(EvalError::OverflowingPointerMath)
|
||||
}
|
||||
@@ -283,7 +287,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
alloc.undef_mask.grow(amount, false);
|
||||
} else if size > new_size {
|
||||
self.memory_usage -= size - new_size;
|
||||
self.clear_relocations(ptr.offset(new_size)?, size - new_size)?;
|
||||
self.clear_relocations(ptr.offset(new_size, self.layout)?, size - new_size)?;
|
||||
let alloc = self.get_mut(ptr.alloc_id)?;
|
||||
// `as usize` is fine here, since it is smaller than `size`, which came from a usize
|
||||
alloc.bytes.truncate(new_size as usize);
|
||||
@@ -595,7 +599,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
return Ok(&[]);
|
||||
}
|
||||
self.check_align(ptr, align, size)?;
|
||||
self.check_bounds(ptr.offset(size)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
self.check_bounds(ptr.offset(size, self.layout)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
assert_eq!(ptr.offset as usize as u64, ptr.offset);
|
||||
assert_eq!(size as usize as u64, size);
|
||||
@@ -608,7 +612,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
return Ok(&mut []);
|
||||
}
|
||||
self.check_align(ptr, align, size)?;
|
||||
self.check_bounds(ptr.offset(size)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
self.check_bounds(ptr.offset(size, self.layout)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
let alloc = self.get_mut(ptr.alloc_id)?;
|
||||
assert_eq!(ptr.offset as usize as u64, ptr.offset);
|
||||
assert_eq!(size as usize as u64, size);
|
||||
@@ -930,7 +934,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
|
||||
fn check_relocation_edges(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx> {
|
||||
let overlapping_start = self.relocations(ptr, 0)?.count();
|
||||
let overlapping_end = self.relocations(ptr.offset(size)?, 0)?.count();
|
||||
let overlapping_end = self.relocations(ptr.offset(size, self.layout)?, 0)?.count();
|
||||
if overlapping_start + overlapping_end != 0 {
|
||||
return Err(EvalError::ReadPointerAsBytes);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user