Skip to content

Commit 9257894

Browse files
committed
miri: fix out-of-bounds error for ptrs with negative offsets
1 parent 6b3ae3f commit 9257894

File tree

7 files changed

+78
-22
lines changed

7 files changed

+78
-22
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,19 +294,22 @@ const_eval_pointer_arithmetic_overflow =
294294
overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
295295
296296
const_eval_pointer_out_of_bounds =
297-
{const_eval_bad_pointer_op_attempting}, but got {$pointer} which {$inbounds_size_is_neg ->
298-
[false] {$alloc_size_minus_ptr_offset ->
299-
[0] is at or beyond the end of the allocation of size {$alloc_size ->
300-
[1] 1 byte
301-
*[x] {$alloc_size} bytes
297+
{const_eval_bad_pointer_op_attempting}, but got {$pointer} which {$ptr_offset_is_neg ->
298+
[true] points to before the beginning of the allocation
299+
*[false] {$inbounds_size_is_neg ->
300+
[false] {$alloc_size_minus_ptr_offset ->
301+
[0] is at or beyond the end of the allocation of size {$alloc_size ->
302+
[1] 1 byte
303+
*[x] {$alloc_size} bytes
304+
}
305+
[1] is only 1 byte from the end of the allocation
306+
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
307+
}
308+
*[true] {$ptr_offset_abs ->
309+
[0] is at the beginning of the allocation
310+
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
302311
}
303-
[1] is only 1 byte from the end of the allocation
304-
*[x] is only {$alloc_size_minus_ptr_offset} bytes from the end of the allocation
305-
}
306-
*[true] {$ptr_offset_abs ->
307-
[0] is at the beginning of the allocation
308-
*[other] is only {$ptr_offset_abs} bytes from the beginning of the allocation
309-
}
312+
}
310313
}
311314
312315
const_eval_pointer_use_after_free =
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
let v: Vec<u16> = vec![1, 2];
3+
// This read is also misaligned. We make sure that the OOB message has priority.
4+
let x = unsafe { *v.as_ptr().wrapping_byte_sub(5) }; //~ ERROR: before the beginning of the allocation
5+
panic!("this should never print: {}", x);
6+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: Undefined Behavior: memory access failed: attempting to access 2 bytes, but got ALLOC-0x5 which points to before the beginning of the allocation
2+
--> tests/fail/dangling_pointers/out_of_bounds_read_neg_offset.rs:LL:CC
3+
|
4+
LL | let x = unsafe { *v.as_ptr().wrapping_byte_sub(5) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
help: ALLOC was allocated here:
10+
--> tests/fail/dangling_pointers/out_of_bounds_read_neg_offset.rs:LL:CC
11+
|
12+
LL | let v: Vec<u16> = vec![1, 2];
13+
| ^^^^^^^^^^
14+
= note: BACKTRACE (of the first span):
15+
= note: inside `main` at tests/fail/dangling_pointers/out_of_bounds_read_neg_offset.rs:LL:CC
16+
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
17+
18+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
19+
20+
error: aborting due to 1 previous error
21+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
let v = [0i8; 4];
3+
let x = &v as *const i8;
4+
let x = unsafe { x.wrapping_offset(-1).offset(-1) }; //~ERROR: before the beginning of the allocation
5+
panic!("this should never print: {:?}", x);
6+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: in-bounds pointer arithmetic failed: attempting to offset pointer by -1 bytes, but got ALLOC-0x1 which points to before the beginning of the allocation
2+
--> tests/fail/intrinsics/ptr_offset_out_of_bounds_neg2.rs:LL:CC
3+
|
4+
LL | let x = unsafe { x.wrapping_offset(-1).offset(-1) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
help: ALLOC was allocated here:
10+
--> tests/fail/intrinsics/ptr_offset_out_of_bounds_neg2.rs:LL:CC
11+
|
12+
LL | let v = [0i8; 4];
13+
| ^
14+
= note: BACKTRACE (of the first span):
15+
= note: inside `main` at tests/fail/intrinsics/ptr_offset_out_of_bounds_neg2.rs:LL:CC
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to 1 previous error
20+

tests/ui/consts/offset_ub.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ use std::ptr;
55
//@ normalize-stderr: "\d+ bytes" -> "$$BYTES bytes"
66

77

8-
pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~ ERROR
9-
pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; //~ ERROR
10-
pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; //~ ERROR
8+
pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~ ERROR: is at the beginning of the allocation
9+
pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; //~ ERROR: only 1 byte from the end of the allocation
10+
pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; //~ ERROR: only 100 bytes from the end of the allocation
1111

12-
pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; //~ ERROR
13-
pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; //~ ERROR
12+
pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; //~ ERROR: does not fit in an `isize`
13+
pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; //~ ERROR: does not fit in an `isize`
1414
pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; //~ ERROR
1515
pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; //~ ERROR
16-
pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; //~ ERROR
16+
pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) }; //~ ERROR: before the beginning of the allocation
1717

18-
pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; //~ ERROR
18+
pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; //~ ERROR: at or beyond the end of the allocation
1919
pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) }; //~ ERROR
2020

2121
// Make sure that we don't panic when computing abs(offset*size_of::<T>())

tests/ui/consts/offset_ub.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer
4040
LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNDERFLOW_ADDRESS_SPACE` failed here
4242

43-
error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got ALLOC3-0x2 which is only $BYTES bytes from the beginning of the allocation
43+
error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by -$BYTES bytes, but got ALLOC3-0x2 which points to before the beginning of the allocation
4444
--> $DIR/offset_ub.rs:16:49
4545
|
46-
LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
47-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `NEGATIVE_OFFSET` failed here
46+
LL | ...*const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `NEGATIVE_OFFSET` failed here
4848

4949
error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by 1 byte, but got ALLOC4 which is at or beyond the end of the allocation of size $BYTES bytes
5050
--> $DIR/offset_ub.rs:18:50

0 commit comments

Comments
 (0)