Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 7d5415b

Browse files
committed
Add additional checks for isize overflow
We now perform the correct checks even if the pointer size differs between the host and target. Signed-off-by: Joe Richey <[email protected]>
1 parent 71ef841 commit 7d5415b

File tree

3 files changed

+17
-7
lines changed

3 files changed

+17
-7
lines changed

src/librustc_middle/mir/interpret/pointer.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ pub trait PointerArithmetic: HasDataLayout {
2424
u64::try_from(max_usize_plus_1 - 1).unwrap()
2525
}
2626

27+
#[inline]
28+
fn machine_isize_min(&self) -> i64 {
29+
let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1);
30+
i64::try_from(-max_isize_plus_1).unwrap()
31+
}
32+
2733
#[inline]
2834
fn machine_isize_max(&self) -> i64 {
2935
let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1);
@@ -42,18 +48,23 @@ pub trait PointerArithmetic: HasDataLayout {
4248

4349
#[inline]
4450
fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
51+
// We do not need to check if i fits in a machine usize. If it doesn't,
52+
// either the wrapping_add will wrap or res will not fit in a pointer.
4553
let res = val.overflowing_add(i);
4654
self.truncate_to_ptr(res)
4755
}
4856

4957
#[inline]
5058
fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
59+
// We need to make sure that i fits in a machine isize.
5160
let n = uabs(i);
5261
if i >= 0 {
53-
self.overflowing_offset(val, n)
62+
let (val, over) = self.overflowing_offset(val, n);
63+
(val, over || i > self.machine_isize_max())
5464
} else {
5565
let res = val.overflowing_sub(n);
56-
self.truncate_to_ptr(res)
66+
let (val, over) = self.truncate_to_ptr(res);
67+
(val, over || i < self.machine_isize_min())
5768
}
5869
}
5970

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
441441
// We cannot overflow i64 as a type's size must be <= isize::MAX.
442442
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
443443
// The computed offset, in bytes, cannot overflow an isize.
444-
let offset_bytes = offset_count
445-
.checked_mul(pointee_size)
446-
.ok_or(err_ub_format!("inbounds pointer arithmetic: overflow computing offset"))?;
444+
let offset_bytes =
445+
offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
447446
// The offset being in bounds cannot rely on "wrapping around" the address space.
448447
// So, first rule out overflows in the pointer arithmetic.
449448
let offset_ptr = ptr.ptr_signed_offset(offset_bytes, self)?;

src/test/ui/consts/offset_ub.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ error: any use of this value will cause an error
5151
LL | intrinsics::offset(self, count)
5252
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5353
| |
54-
| inbounds pointer arithmetic: overflow computing offset
54+
| overflowing in-bounds pointer arithmetic
5555
| inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
5656
| inside `OVERFLOW` at $DIR/offset_ub.rs:11:43
5757
|
@@ -66,7 +66,7 @@ error: any use of this value will cause an error
6666
LL | intrinsics::offset(self, count)
6767
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6868
| |
69-
| inbounds pointer arithmetic: overflow computing offset
69+
| overflowing in-bounds pointer arithmetic
7070
| inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
7171
| inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44
7272
|

0 commit comments

Comments
 (0)