Skip to content

Commit

Permalink
Unrolled build for rust-lang#124923
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#124923 - RalfJung:offset-from-errors, r=compiler-errors

interpret/miri: better errors on failing offset_from

Fixes rust-lang/miri#3104
  • Loading branch information
rust-timer committed May 9, 2024
2 parents 238c1e7 + 41d36a0 commit 5c1a648
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 27 deletions.
15 changes: 8 additions & 7 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@ const_eval_deref_function_pointer =
accessing {$allocation} which contains a function
const_eval_deref_vtable_pointer =
accessing {$allocation} which contains a vtable
const_eval_different_allocations =
`{$name}` called on pointers into different allocations
const_eval_division_by_zero =
dividing by zero
const_eval_division_overflow =
Expand Down Expand Up @@ -234,12 +231,18 @@ const_eval_not_enough_caller_args =
const_eval_nullary_intrinsic_fail =
could not evaluate nullary intrinsic
const_eval_offset_from_different_allocations =
`{$name}` called on pointers into different allocations
const_eval_offset_from_different_integers =
`{$name}` called on different pointers without provenance (i.e., without an associated allocation)
const_eval_offset_from_overflow =
`{$name}` called when first pointer is too far ahead of second
const_eval_offset_from_test = out-of-bounds `offset_from`
const_eval_offset_from_test =
out-of-bounds `offset_from`
const_eval_offset_from_underflow =
`{$name}` called when first pointer is too far before second
const_eval_offset_from_unsigned_overflow =
`ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
const_eval_operator_non_const =
cannot call non-const operator in {const_eval_const_context}s
Expand Down Expand Up @@ -381,8 +384,6 @@ const_eval_unreachable = entering unreachable code
const_eval_unreachable_unwind =
unwinding past a stack frame that does not allow unwinding
const_eval_unsigned_offset_from_overflow =
`ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
const_eval_unsized_local = unsized locals are not supported
const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
Expand Down
29 changes: 16 additions & 13 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,16 @@ use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{Ty, TyCtxt};
use rustc_middle::{
mir::{
self,
interpret::{
Allocation, ConstAllocation, GlobalId, InterpResult, PointerArithmetic, Scalar,
},
BinOp, ConstValue, NonDivergingIntrinsic,
},
mir::{self, BinOp, ConstValue, NonDivergingIntrinsic},
ty::layout::TyAndLayout,
};
use rustc_span::symbol::{sym, Symbol};
use rustc_target::abi::Size;

use super::{
memory::MemoryKind, util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx,
MPlaceTy, Machine, OpTy, Pointer,
memory::MemoryKind, util::ensure_monomorphic_enough, Allocation, CheckInAllocMsg,
ConstAllocation, GlobalId, ImmTy, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Pointer,
PointerArithmetic, Scalar,
};

use crate::fluent_generated as fluent;
Expand Down Expand Up @@ -249,22 +244,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match (self.ptr_try_get_alloc_id(a), self.ptr_try_get_alloc_id(b)) {
(Err(a), Err(b)) => {
// Neither pointer points to an allocation.
// If these are inequal or null, this *will* fail the deref check below.
// This is okay only if they are the same.
if a != b {
// We'd catch this below in the "dereferenceable" check, but
// show a nicer error for this particular case.
throw_ub_custom!(
fluent::const_eval_offset_from_different_integers,
name = intrinsic_name,
);
}
(a, b)
}
(Err(_), _) | (_, Err(_)) => {
// We managed to find a valid allocation for one pointer, but not the other.
// That means they are definitely not pointing to the same allocation.
throw_ub_custom!(
fluent::const_eval_different_allocations,
fluent::const_eval_offset_from_different_allocations,
name = intrinsic_name,
);
}
(Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
// Found allocation for both. They must be into the same allocation.
if a_alloc_id != b_alloc_id {
throw_ub_custom!(
fluent::const_eval_different_allocations,
fluent::const_eval_offset_from_different_allocations,
name = intrinsic_name,
);
}
Expand All @@ -286,7 +289,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// a < b
if intrinsic_name == sym::ptr_offset_from_unsigned {
throw_ub_custom!(
fluent::const_eval_unsigned_offset_from_overflow,
fluent::const_eval_offset_from_unsigned_overflow,
a_offset = a_offset,
b_offset = b_offset,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#![feature(strict_provenance)]
use core::ptr;

fn main() {
unsafe {
let base = ptr::without_provenance::<()>(10);
let unit = &*base;
let p1 = unit as *const ();

let base = ptr::without_provenance::<()>(11);
let unit = &*base;
let p2 = unit as *const ();

// Seems to work because they are same pointer
// even though it's dangling.
let _ = p1.byte_offset_from(p1);

// UB because different pointers.
let _ = p1.byte_offset_from(p2); //~ERROR: different pointers without provenance
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: Undefined Behavior: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
--> $DIR/ptr_offset_from_different_ints.rs:LL:CC
|
LL | let _ = p1.byte_offset_from(p2);
| ^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated 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 $DIR/ptr_offset_from_different_ints.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

8 changes: 4 additions & 4 deletions tests/ui/consts/offset_from_ub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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
//~| 0x8[noalloc] is a dangling pointer
//~| different pointers without provenance
};

const OUT_OF_BOUNDS_1: isize = {
Expand Down Expand Up @@ -81,13 +81,13 @@ pub const DIFFERENT_ALLOC_UNSIGNED: usize = {
};

pub const TOO_FAR_APART1: isize = {
let ptr1 = ptr::null::<u8>();
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
//~| too far ahead
};
pub const TOO_FAR_APART2: isize = {
let ptr1 = ptr::null::<u8>();
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
//~| too far before
Expand All @@ -100,7 +100,7 @@ const WRONG_ORDER_UNSIGNED: usize = {
//~| first pointer has smaller offset than second: 0 < 8
};
pub const TOO_FAR_APART_UNSIGNED: usize = {
let ptr1 = ptr::null::<u8>();
let ptr1 = &0u8 as *const u8;
let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
// This would fit into a `usize` but we still don't allow it.
unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } //~ERROR evaluation of constant value failed
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/consts/offset_from_ub.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ error[E0080]: evaluation of constant value failed
--> $DIR/offset_from_ub.rs:44:14
|
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0x8[noalloc] is a dangling pointer (it has no provenance)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)

error[E0080]: evaluation of constant value failed
--> $DIR/offset_from_ub.rs:53:14
Expand Down Expand Up @@ -86,7 +86,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`: null pointer is a dangling pointer (it has no provenance)
= note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
Expand All @@ -99,7 +99,7 @@ LL | unsafe { ptr2.offset_from(ptr1) }
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
= note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
= note: `ptr_offset_from` called on different pointers without provenance (i.e., without an associated allocation)
|
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
Expand Down

0 comments on commit 5c1a648

Please sign in to comment.