mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
fix the way we detect overflow for inbounds arithmetic (and tweak the error message)
This commit is contained in:
parent
5d5c97aad7
commit
db1652e07b
@ -277,7 +277,7 @@ const_eval_partial_pointer_copy =
|
|||||||
const_eval_partial_pointer_overwrite =
|
const_eval_partial_pointer_overwrite =
|
||||||
unable to overwrite parts of a pointer in memory at {$ptr}
|
unable to overwrite parts of a pointer in memory at {$ptr}
|
||||||
const_eval_pointer_arithmetic_overflow =
|
const_eval_pointer_arithmetic_overflow =
|
||||||
overflowing in-bounds pointer arithmetic
|
overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
|
||||||
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
|
const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
|
||||||
const_eval_pointer_out_of_bounds =
|
const_eval_pointer_out_of_bounds =
|
||||||
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
|
{$bad_pointer_message}: {const_eval_expected_inbounds_pointer}, but got {$pointer} {$ptr_offset_is_neg ->
|
||||||
|
@ -7,7 +7,7 @@ use rustc_middle::{bug, mir, span_bug};
|
|||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use super::{err_ub, throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta};
|
use super::{throw_ub, ImmTy, InterpCx, Machine, MemPlaceMeta};
|
||||||
|
|
||||||
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
|
fn three_way_compare<T: Ord>(&self, lhs: T, rhs: T) -> ImmTy<'tcx, M::Provenance> {
|
||||||
@ -298,17 +298,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
// Pointer ops that are always supported.
|
// Pointer ops that are always supported.
|
||||||
Offset => {
|
Offset => {
|
||||||
let ptr = left.to_scalar().to_pointer(self)?;
|
let ptr = left.to_scalar().to_pointer(self)?;
|
||||||
let offset_count = right.to_scalar().to_target_isize(self)?;
|
|
||||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
|
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
|
||||||
|
let pointee_layout = self.layout_of(pointee_ty)?;
|
||||||
|
assert!(pointee_layout.abi.is_sized());
|
||||||
|
|
||||||
// We cannot overflow i64 as a type's size must be <= isize::MAX.
|
// We cannot overflow i64 as a type's size must be <= isize::MAX.
|
||||||
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
|
let pointee_size = i64::try_from(pointee_layout.size.bytes()).unwrap();
|
||||||
// The computed offset, in bytes, must not overflow an isize.
|
let pointee_size = ImmTy::from_int(pointee_size, right.layout);
|
||||||
// `checked_mul` enforces a too small bound, but no actual allocation can be big enough for
|
// Multiply element size and element count.
|
||||||
// the difference to be noticeable.
|
let (val, overflowed) = self
|
||||||
let offset_bytes =
|
.binary_op(mir::BinOp::MulWithOverflow, right, &pointee_size)?
|
||||||
offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
|
.to_scalar_pair();
|
||||||
|
// This must not overflow.
|
||||||
|
if overflowed.to_bool()? {
|
||||||
|
throw_ub!(PointerArithOverflow)
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset_bytes = val.to_target_isize(self)?;
|
||||||
let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?;
|
let offset_ptr = self.ptr_offset_inbounds(ptr, offset_bytes)?;
|
||||||
Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout))
|
Ok(ImmTy::from_scalar(Scalar::from_maybe_pointer(offset_ptr, self), left.layout))
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101)
|
|||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: overflowing in-bounds pointer arithmetic
|
= note: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
|
||||||
|
|
|
|
||||||
note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
|
note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
|
||||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
@ -53,7 +53,7 @@ LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::
|
|||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: overflowing in-bounds pointer arithmetic
|
= note: overflowing pointer arithmetic: the total offset in bytes does not fit in an `isize`
|
||||||
|
|
|
|
||||||
note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
|
note: inside `std::ptr::const_ptr::<impl *const u16>::offset`
|
||||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
Loading…
Reference in New Issue
Block a user