Skip to content

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

+13-2
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

+2-3
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

+2-2
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)