about summary refs log tree commit diff
path: root/compiler/rustc_const_eval/src/interpret
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2024-09-11 15:53:24 -0700
committerGitHub <noreply@github.com>2024-09-11 15:53:24 -0700
commit142598214cd3cf1705a9b3900897e226daee2aed (patch)
treea3363376a4dc9aee3574ef2df8c9b868e105b68d /compiler/rustc_const_eval/src/interpret
parent1e3d1ad4bcb25c219863def5f7f7a0e1d6c1a662 (diff)
parent3842ea671bfb98b2a7a42edbd31c5bac89078024 (diff)
Rollup merge of #130239 - RalfJung:miri-ptr-offset-unsigned, r=compiler-errors
miri: fix overflow detection for unsigned pointer offset

This is the Miri part of https://github.com/rust-lang/rust/pull/130229. This is already UB in codegen so we better make Miri detect it; updating the docs may take time if we have to follow some approval process, but let's make Miri match reality ASAP.

r? ``@scottmcm``
Diffstat (limited to 'compiler/rustc_const_eval/src/interpret')
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs9
1 files changed, 8 insertions, 1 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index e9ba12dbcc4..b390bb87789 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -303,8 +303,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let pointee_layout = self.layout_of(pointee_ty)?;
                 assert!(pointee_layout.abi.is_sized());
 
-                // We cannot overflow i64 as a type's size must be <= isize::MAX.
+                // The size always fits in `i64` as it can be at most `isize::MAX`.
                 let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap();
+                // This uses the same type as `right`, which can be `isize` or `usize`.
+                // `pointee_size` is guaranteed to fit into both types.
                 let pointee_size = ImmTy::from_int(pointee_size, right.layout);
                 // Multiply element size and element count.
                 let (val, overflowed) = self
@@ -316,6 +318,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 }
 
                 let offset_bytes = val.to_target_isize(self)?;
+                if !right.layout.abi.is_signed() && offset_bytes < 0 {
+                    // We were supposed to do an unsigned offset but the result is negative -- this
+                    // can only mean that the cast wrapped around.
+                    throw_ub!(PointerArithOverflow)
+                }
                 let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?;
                 Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout))
             }