Rollup merge of #136438 - RalfJung:offset_from_ub_errors, r=oli-obk
miri: improve error when offset_from preconditions are violated Fixes https://github.com/rust-lang/miri/issues/4143
This commit is contained in:
commit
43764db758
11 changed files with 81 additions and 19 deletions
|
@ -280,7 +280,9 @@ const_eval_nullary_intrinsic_fail =
|
|||
could not evaluate nullary intrinsic
|
||||
|
||||
const_eval_offset_from_different_allocations =
|
||||
`{$name}` called on pointers into different allocations
|
||||
`{$name}` called on two different pointers that are not both derived from the same allocation
|
||||
const_eval_offset_from_out_of_bounds =
|
||||
`{$name}` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
const_eval_offset_from_overflow =
|
||||
`{$name}` called when first pointer is too far ahead of second
|
||||
const_eval_offset_from_test =
|
||||
|
|
|
@ -319,7 +319,25 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
|
||||
// Check that the memory between them is dereferenceable at all, starting from the
|
||||
// origin pointer: `dist` is `a - b`, so it is based on `b`.
|
||||
self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)?;
|
||||
self.check_ptr_access_signed(b, dist, CheckInAllocMsg::OffsetFromTest)
|
||||
.map_err_kind(|_| {
|
||||
// This could mean they point to different allocations, or they point to the same allocation
|
||||
// but not the entire range between the pointers is in-bounds.
|
||||
if let Ok((a_alloc_id, ..)) = self.ptr_try_get_alloc_id(a, 0)
|
||||
&& let Ok((b_alloc_id, ..)) = self.ptr_try_get_alloc_id(b, 0)
|
||||
&& a_alloc_id == b_alloc_id
|
||||
{
|
||||
err_ub_custom!(
|
||||
fluent::const_eval_offset_from_out_of_bounds,
|
||||
name = intrinsic_name,
|
||||
)
|
||||
} else {
|
||||
err_ub_custom!(
|
||||
fluent::const_eval_offset_from_different_allocations,
|
||||
name = intrinsic_name,
|
||||
)
|
||||
}
|
||||
})?;
|
||||
// Then check that this is also dereferenceable from `a`. This ensures that they are
|
||||
// derived from the same allocation.
|
||||
self.check_ptr_access_signed(
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
unsafe {
|
||||
(&1_u8 as *const u8).offset_from(&2_u8); //~ERROR: not both derived from the same allocation
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
error: Undefined Behavior: `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
--> tests/fail/intrinsics/ptr_offset_from_different_allocs.rs:LL:CC
|
||||
|
|
||||
LL | (&1_u8 as *const u8).offset_from(&2_u8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at tests/fail/intrinsics/ptr_offset_from_different_allocs.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -15,6 +15,6 @@ fn main() {
|
|||
let _ = p1.byte_offset_from(p1);
|
||||
|
||||
// UB because different pointers.
|
||||
let _ = p1.byte_offset_from(p2); //~ERROR: no provenance
|
||||
let _ = p1.byte_offset_from(p2); //~ERROR: not both derived from the same allocation
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: Undefined Behavior: out-of-bounds `offset_from` origin: expected a pointer to the end of 1 byte of memory, but got 0xb[noalloc] which is a dangling pointer (it has no provenance)
|
||||
error: Undefined Behavior: `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
--> tests/fail/intrinsics/ptr_offset_from_different_ints.rs:LL:CC
|
||||
|
|
||||
LL | let _ = p1.byte_offset_from(p2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of 1 byte of memory, but got 0xb[noalloc] which is a dangling pointer (it has no provenance)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
fn main() {
|
||||
let mem = [0u8; 1];
|
||||
let ptr = mem.as_ptr();
|
||||
unsafe {
|
||||
ptr.wrapping_add(4).offset_from(ptr); //~ERROR: the memory range between them is not in-bounds of an allocation
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
error: Undefined Behavior: `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
--> tests/fail/intrinsics/ptr_offset_from_oob.rs:LL:CC
|
||||
|
|
||||
LL | ptr.wrapping_add(4).offset_from(ptr);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at tests/fail/intrinsics/ptr_offset_from_oob.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -190,7 +190,7 @@ LL | from_ptr_range(ptr..ptr.add(1))
|
|||
error[E0080]: could not evaluate static initializer
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
||||
= note: `ptr_offset_from_unsigned` called on pointers into different allocations
|
||||
= note: `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
||||
note: inside `std::ptr::const_ptr::<impl *const u32>::sub_ptr`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
@ -205,7 +205,7 @@ LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).ad
|
|||
error[E0080]: could not evaluate static initializer
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
||||
= note: `ptr_offset_from_unsigned` called on pointers into different allocations
|
||||
= note: `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
||||
note: inside `std::ptr::const_ptr::<impl *const u32>::sub_ptr`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
|
@ -17,7 +17,7 @@ pub const DIFFERENT_ALLOC: usize = {
|
|||
let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
|
||||
let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
|
||||
let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
|
||||
//~| pointers into different allocations
|
||||
//~| not both derived from the same allocation
|
||||
offset as usize
|
||||
};
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub const DIFFERENT_INT: isize = { // offset_from with two different integers: l
|
|||
let ptr1 = 8 as *const u8;
|
||||
let ptr2 = 16 as *const u8;
|
||||
unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
|
||||
//~| dangling pointer
|
||||
//~| not both derived from the same allocation
|
||||
};
|
||||
|
||||
const OUT_OF_BOUNDS_1: isize = {
|
||||
|
@ -46,7 +46,7 @@ const OUT_OF_BOUNDS_1: isize = {
|
|||
let end_ptr = (start_ptr).wrapping_add(length);
|
||||
// First ptr is out of bounds
|
||||
unsafe { ptr_offset_from(end_ptr, start_ptr) } //~ERROR evaluation of constant value failed
|
||||
//~| expected a pointer to 10 bytes of memory
|
||||
//~| the memory range between them is not in-bounds of an allocation
|
||||
};
|
||||
|
||||
const OUT_OF_BOUNDS_2: isize = {
|
||||
|
@ -55,7 +55,7 @@ const OUT_OF_BOUNDS_2: isize = {
|
|||
let end_ptr = (start_ptr).wrapping_add(length);
|
||||
// Second ptr is out of bounds
|
||||
unsafe { ptr_offset_from(start_ptr, end_ptr) } //~ERROR evaluation of constant value failed
|
||||
//~| expected a pointer to the end of 10 bytes of memory
|
||||
//~| the memory range between them is not in-bounds of an allocation
|
||||
};
|
||||
|
||||
pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
|
||||
|
@ -64,7 +64,7 @@ pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
|
|||
let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
|
||||
let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
|
||||
unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } //~ERROR evaluation of constant value failed
|
||||
//~| pointers into different allocations
|
||||
//~| not both derived from the same allocation
|
||||
};
|
||||
|
||||
pub const TOO_FAR_APART1: isize = {
|
||||
|
|
|
@ -2,12 +2,12 @@ error[E0080]: evaluation of constant value failed
|
|||
--> $DIR/offset_from_ub.rs:19:27
|
||||
|
|
||||
LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
||||
= note: `ptr_offset_from` called on pointers into different allocations
|
||||
= note: `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
||||
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
@ -27,25 +27,25 @@ error[E0080]: evaluation of constant value failed
|
|||
--> $DIR/offset_from_ub.rs:39:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got 0x8[noalloc] which is a dangling pointer (it has no provenance)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:48:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(end_ptr, start_ptr) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got ALLOC0 which is only $BYTES bytes from the end of the allocation
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:57:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(start_ptr, end_ptr) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of $BYTES bytes of memory, but got ALLOC1+0xa which does not have enough space to the beginning of the allocation
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:66:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:73:14
|
||||
|
@ -80,7 +80,7 @@ LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
|
|||
error[E0080]: evaluation of constant value failed
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
||||
= note: out-of-bounds `offset_from` origin: expected a pointer to $BYTES bytes of memory, but got a null pointer
|
||||
= note: `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
||||
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue