From edf28fa227c68267153dc42119f3170f46b14389 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 8 Oct 2018 10:22:26 +0200 Subject: [PATCH 1/2] only allow offset-by-0 on integer pointers --- src/operator.rs | 18 +++++++----------- tests/compile-fail/ptr_offset_int_plus_int.rs | 8 ++++++++ 2 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 tests/compile-fail/ptr_offset_int_plus_int.rs diff --git a/src/operator.rs b/src/operator.rs index cf416c44c1..6fed43914e 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -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))?; @@ -301,9 +293,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: self.memory.check_bounds(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) + } } } } diff --git a/tests/compile-fail/ptr_offset_int_plus_int.rs b/tests/compile-fail/ptr_offset_int_plus_int.rs new file mode 100644 index 0000000000..fa4efa3236 --- /dev/null +++ b/tests/compile-fail/ptr_offset_int_plus_int.rs @@ -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); + } +} From 0641d5b6d30a6f66bfd8ec1ff06bc7170569e6a1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 8 Oct 2018 11:22:52 +0200 Subject: [PATCH 2/2] 0-offset is also not always okay --- tests/compile-fail/ptr_offset_ptr_plus_0.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/compile-fail/ptr_offset_ptr_plus_0.rs diff --git a/tests/compile-fail/ptr_offset_ptr_plus_0.rs b/tests/compile-fail/ptr_offset_ptr_plus_0.rs new file mode 100644 index 0000000000..46937b1c8c --- /dev/null +++ b/tests/compile-fail/ptr_offset_ptr_plus_0.rs @@ -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 +}