const-eval: improve and actually test the errors when pointers might be outside the range of a scalar
This commit is contained in:
parent
29005cb128
commit
0a41add629
8 changed files with 49 additions and 21 deletions
|
|
@ -479,11 +479,11 @@ const_eval_validation_never_val = {$front_matter}: encountered a value of the ne
|
|||
const_eval_validation_null_box = {$front_matter}: encountered a null box
|
||||
const_eval_validation_null_fn_ptr = {$front_matter}: encountered a null function pointer
|
||||
const_eval_validation_null_ref = {$front_matter}: encountered a null reference
|
||||
const_eval_validation_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_validation_nonnull_ptr_out_of_range = {$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero
|
||||
const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
|
||||
const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
|
||||
const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
|
||||
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
|
||||
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}
|
||||
const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
|
||||
const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
|
||||
NullFnPtr => const_eval_validation_null_fn_ptr,
|
||||
NeverVal => const_eval_validation_never_val,
|
||||
NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
|
||||
NonnullPtrMaybeNull { .. } => const_eval_validation_nonnull_ptr_out_of_range,
|
||||
PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
|
||||
OutOfRange { .. } => const_eval_validation_out_of_range,
|
||||
UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
|
||||
|
|
@ -804,9 +804,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
| InvalidFnPtr { value } => {
|
||||
err.arg("value", value);
|
||||
}
|
||||
NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
|
||||
add_range_arg(range, max_value, err)
|
||||
}
|
||||
PtrOutOfRange { range, max_value } => add_range_arg(range, max_value, err),
|
||||
OutOfRange { range, max_value, value } => {
|
||||
err.arg("value", value);
|
||||
add_range_arg(range, max_value, err);
|
||||
|
|
@ -826,6 +824,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
|
|||
| MutableRefToImmutable
|
||||
| MutableRefInConst
|
||||
| NullFnPtr
|
||||
| NonnullPtrMaybeNull
|
||||
| NeverVal
|
||||
| UnsafeCellInImmutable
|
||||
| InvalidMetaSliceTooLarge { .. }
|
||||
|
|
|
|||
|
|
@ -819,10 +819,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
if start == 1 && end == max_value {
|
||||
// Only null is the niche. So make sure the ptr is NOT null.
|
||||
if self.ecx.scalar_may_be_null(scalar)? {
|
||||
throw_validation_failure!(
|
||||
self.path,
|
||||
NullablePtrOutOfRange { range: valid_range, max_value }
|
||||
)
|
||||
throw_validation_failure!(self.path, NonnullPtrMaybeNull)
|
||||
} else {
|
||||
return interp_ok(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -499,10 +499,7 @@ pub enum ValidationErrorKind<'tcx> {
|
|||
MutableRefInConst,
|
||||
NullFnPtr,
|
||||
NeverVal,
|
||||
NullablePtrOutOfRange {
|
||||
range: WrappingRange,
|
||||
max_value: u128,
|
||||
},
|
||||
NonnullPtrMaybeNull,
|
||||
PtrOutOfRange {
|
||||
range: WrappingRange,
|
||||
max_value: u128,
|
||||
|
|
|
|||
|
|
@ -57,4 +57,8 @@ const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
|
|||
mem::transmute((0_usize, meta))
|
||||
};
|
||||
|
||||
static S: u32 = 0; // just a static to construct a maybe-null pointer off of
|
||||
const MAYBE_NULL_PTR: NonNull<()> = unsafe { mem::transmute((&raw const S).wrapping_add(4)) };
|
||||
//~^ ERROR invalid value
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
|
|||
HEX_DUMP
|
||||
}
|
||||
|
||||
error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by 255 bytes, but got ALLOC1 which is only 1 byte from the end of the allocation
|
||||
error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer by 255 bytes, but got ALLOC2 which is only 1 byte from the end of the allocation
|
||||
--> $DIR/ub-nonnull.rs:22:29
|
||||
|
|
||||
LL | let out_of_bounds_ptr = &ptr[255];
|
||||
|
|
@ -37,7 +37,7 @@ LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
|
|||
HEX_DUMP
|
||||
}
|
||||
|
||||
error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
|
||||
error[E0080]: reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
|
||||
--> $DIR/ub-nonnull.rs:36:38
|
||||
|
|
||||
LL | const UNINIT: NonZero<u8> = unsafe { MaybeUninit { uninit: () }.init };
|
||||
|
|
@ -80,6 +80,17 @@ LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
|
|||
HEX_DUMP
|
||||
}
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error[E0080]: constructing invalid value: encountered a maybe-null pointer, but expected something that is definitely non-zero
|
||||
--> $DIR/ub-nonnull.rs:61:1
|
||||
|
|
||||
LL | const MAYBE_NULL_PTR: NonNull<()> = unsafe { mem::transmute((&raw const S).wrapping_add(4)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
|
||||
|
|
||||
= note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||
//@ dont-require-annotations: NOTE
|
||||
//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(invalid_value)]
|
||||
|
||||
use std::mem;
|
||||
|
|
@ -65,5 +65,14 @@ const UNALIGNED_READ: () = unsafe {
|
|||
ptr.read(); //~ ERROR accessing memory
|
||||
};
|
||||
|
||||
// Check the general case of a pointer value not falling into the scalar valid range.
|
||||
#[rustc_layout_scalar_valid_range_start(1000)]
|
||||
pub struct High {
|
||||
pointer: *const (),
|
||||
}
|
||||
static S: u32 = 0; // just a static to construct a pointer with unknown absolute address
|
||||
const INVALID_VALUE_PTR: High = unsafe { mem::transmute(&S) };
|
||||
//~^ ERROR invalid value
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
|
|||
HEX_DUMP
|
||||
}
|
||||
|
||||
error[E0080]: reading memory at ALLOC3[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
|
||||
error[E0080]: reading memory at ALLOC4[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
|
||||
--> $DIR/ub-ref-ptr.rs:49:41
|
||||
|
|
||||
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
|
||||
|
|
@ -124,7 +124,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
|
|||
HEX_DUMP
|
||||
}
|
||||
|
||||
error[E0080]: reading memory at ALLOC4[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
|
||||
error[E0080]: reading memory at ALLOC5[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
|
||||
--> $DIR/ub-ref-ptr.rs:54:38
|
||||
|
|
||||
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
|
||||
|
|
@ -162,6 +162,17 @@ error[E0080]: accessing memory based on pointer with alignment 1, but alignment
|
|||
LL | ptr.read();
|
||||
| ^^^^^^^^^^ evaluation of `UNALIGNED_READ` failed here
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
error[E0080]: constructing invalid value: encountered a pointer with unknown absolute address, but expected something that is definitely greater or equal to 1000
|
||||
--> $DIR/ub-ref-ptr.rs:74:1
|
||||
|
|
||||
LL | const INVALID_VALUE_PTR: High = unsafe { mem::transmute(&S) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
|
||||
|
|
||||
= note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue