From 4bb15b3797452b87c6ea3189fa60dd52d59a567d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 9 Apr 2022 16:29:39 -0700 Subject: [PATCH] Add a debug check for ordering, and check for isize overflow in CTFE --- .../rustc_const_eval/src/interpret/intrinsics.rs | 13 ++++++++++--- library/core/src/ptr/const_ptr.rs | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index f6dd02a9abac..3bb3b3d53932 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -365,10 +365,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { usize_layout }; - let a_offset = ImmTy::from_uint(a_offset.bytes(), usize_layout); - let b_offset = ImmTy::from_uint(b_offset.bytes(), usize_layout); - let (val, _overflowed, _ty) = + + // The subtraction is always done in `isize` to enforce + // the "no more than `isize::MAX` apart" requirement. + let a_offset = ImmTy::from_uint(a_offset.bytes(), isize_layout); + let b_offset = ImmTy::from_uint(b_offset.bytes(), isize_layout); + let (val, overflowed, _ty) = self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?; + if overflowed { + throw_ub_format!("Pointers were too far apart for {}", intrinsic_name); + } + let pointee_layout = self.layout_of(substs.type_at(0))?; let val = ImmTy::from_scalar(val, ret_layout); let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout); diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 5be855bfabb5..7fcdf21b03cd 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -678,6 +678,10 @@ impl *const T { where T: Sized, { + // SAFETY: The comparison has no side-effects, and the intrinsic + // does this check internally in the CTFE implementation. + unsafe { assert_unsafe_precondition!(self >= origin) }; + let pointee_size = mem::size_of::(); assert!(0 < pointee_size && pointee_size <= isize::MAX as usize); // SAFETY: the caller must uphold the safety contract for `ptr_offset_from_unsigned`.