Skip to content

Commit

Permalink
Merge pull request #470 from RalfJung/ptr-offset
Browse files Browse the repository at this point in the history
only allow 0-offset on integer pointers
  • Loading branch information
RalfJung authored Oct 10, 2018
2 parents 5a496dd + a439262 commit 15a0004
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 11 deletions.
18 changes: 7 additions & 11 deletions src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
pointee_ty: Ty<'tcx>,
offset: i64,
) -> EvalResult<'tcx, Scalar> {
if ptr.is_null() {
// NULL pointers must only be offset by 0
return if offset == 0 {
Ok(ptr)
} else {
err!(InvalidNullPointerUsage)
};
}
// FIXME: assuming here that type size is < i64::max_value()
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
let offset = offset.checked_mul(pointee_size).ok_or_else(|| EvalErrorKind::Overflow(mir::BinOp::Mul))?;
Expand All @@ -301,9 +293,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
self.memory.check_bounds_ptr(ptr, false)?;
Ok(Scalar::Ptr(ptr))
} else {
// An integer pointer. They can move around freely, as long as they do not overflow
// (which ptr_signed_offset checks).
ptr.ptr_signed_offset(offset, self)
// An integer pointer. They can only be offset by 0, and we pretend there
// is a little zero-sized allocation here.
if offset == 0 {
Ok(ptr)
} else {
err!(InvalidPointerMath)
}
}
}
}
8 changes: 8 additions & 0 deletions tests/compile-fail/ptr_offset_int_plus_int.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// error-pattern: invalid arithmetic on pointers

fn main() {
// Can't offset an integer pointer by non-zero offset.
unsafe {
let _ = (1 as *mut u8).offset(1);
}
}
7 changes: 7 additions & 0 deletions tests/compile-fail/ptr_offset_ptr_plus_0.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// error-pattern: outside bounds of allocation

fn main() {
let x = Box::into_raw(Box::new(0u32));
let x = x.wrapping_offset(8); // okay, this has no inbounds tag
let _x = unsafe { x.offset(0) }; // UB despite offset 0, the pointer is not inbounds of the only object it can point to
}

0 comments on commit 15a0004

Please sign in to comment.