Skip to content

Commit 0a41add

Browse files
committed
const-eval: improve and actually test the errors when pointers might be outside the range of a scalar
1 parent 29005cb commit 0a41add

File tree

8 files changed

+49
-21
lines changed

8 files changed

+49
-21
lines changed

compiler/rustc_const_eval/messages.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -479,11 +479,11 @@ const_eval_validation_never_val = {$front_matter}: encountered a value of the ne
479479
const_eval_validation_null_box = {$front_matter}: encountered a null box
480480
const_eval_validation_null_fn_ptr = {$front_matter}: encountered a null function pointer
481481
const_eval_validation_null_ref = {$front_matter}: encountered a null reference
482-
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}
482+
const_eval_validation_nonnull_ptr_out_of_range = {$front_matter}: encountered a maybe-null pointer, but expected something that is definitely non-zero
483483
const_eval_validation_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
484484
const_eval_validation_partial_pointer = {$front_matter}: encountered a partial pointer or a mix of pointers
485485
const_eval_validation_pointer_as_int = {$front_matter}: encountered a pointer, but {$expected}
486-
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
486+
const_eval_validation_ptr_out_of_range = {$front_matter}: encountered a pointer with unknown absolute address, but expected something that is definitely {$in_range}
487487
const_eval_validation_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
488488
const_eval_validation_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
489489
const_eval_validation_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})

compiler/rustc_const_eval/src/errors.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
668668
MutableRefInConst => const_eval_validation_mutable_ref_in_const,
669669
NullFnPtr => const_eval_validation_null_fn_ptr,
670670
NeverVal => const_eval_validation_never_val,
671-
NullablePtrOutOfRange { .. } => const_eval_validation_nullable_ptr_out_of_range,
671+
NonnullPtrMaybeNull { .. } => const_eval_validation_nonnull_ptr_out_of_range,
672672
PtrOutOfRange { .. } => const_eval_validation_ptr_out_of_range,
673673
OutOfRange { .. } => const_eval_validation_out_of_range,
674674
UnsafeCellInImmutable => const_eval_validation_unsafe_cell,
@@ -804,9 +804,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
804804
| InvalidFnPtr { value } => {
805805
err.arg("value", value);
806806
}
807-
NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
808-
add_range_arg(range, max_value, err)
809-
}
807+
PtrOutOfRange { range, max_value } => add_range_arg(range, max_value, err),
810808
OutOfRange { range, max_value, value } => {
811809
err.arg("value", value);
812810
add_range_arg(range, max_value, err);
@@ -826,6 +824,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
826824
| MutableRefToImmutable
827825
| MutableRefInConst
828826
| NullFnPtr
827+
| NonnullPtrMaybeNull
829828
| NeverVal
830829
| UnsafeCellInImmutable
831830
| InvalidMetaSliceTooLarge { .. }

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -819,10 +819,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
819819
if start == 1 && end == max_value {
820820
// Only null is the niche. So make sure the ptr is NOT null.
821821
if self.ecx.scalar_may_be_null(scalar)? {
822-
throw_validation_failure!(
823-
self.path,
824-
NullablePtrOutOfRange { range: valid_range, max_value }
825-
)
822+
throw_validation_failure!(self.path, NonnullPtrMaybeNull)
826823
} else {
827824
return interp_ok(());
828825
}

compiler/rustc_middle/src/mir/interpret/error.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -499,10 +499,7 @@ pub enum ValidationErrorKind<'tcx> {
499499
MutableRefInConst,
500500
NullFnPtr,
501501
NeverVal,
502-
NullablePtrOutOfRange {
503-
range: WrappingRange,
504-
max_value: u128,
505-
},
502+
NonnullPtrMaybeNull,
506503
PtrOutOfRange {
507504
range: WrappingRange,
508505
max_value: u128,

tests/ui/consts/const-eval/ub-nonnull.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,8 @@ const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
5757
mem::transmute((0_usize, meta))
5858
};
5959

60+
static S: u32 = 0; // just a static to construct a maybe-null pointer off of
61+
const MAYBE_NULL_PTR: NonNull<()> = unsafe { mem::transmute((&raw const S).wrapping_add(4)) };
62+
//~^ ERROR invalid value
63+
6064
fn main() {}

tests/ui/consts/const-eval/ub-nonnull.stderr

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
99
HEX_DUMP
1010
}
1111

12-
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
12+
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
1313
--> $DIR/ub-nonnull.rs:22:29
1414
|
1515
LL | let out_of_bounds_ptr = &ptr[255];
@@ -37,7 +37,7 @@ LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
3737
HEX_DUMP
3838
}
3939

40-
error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
40+
error[E0080]: reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
4141
--> $DIR/ub-nonnull.rs:36:38
4242
|
4343
LL | const UNINIT: NonZero<u8> = unsafe { MaybeUninit { uninit: () }.init };
@@ -80,6 +80,17 @@ LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
8080
HEX_DUMP
8181
}
8282

83-
error: aborting due to 8 previous errors
83+
error[E0080]: constructing invalid value: encountered a maybe-null pointer, but expected something that is definitely non-zero
84+
--> $DIR/ub-nonnull.rs:61:1
85+
|
86+
LL | const MAYBE_NULL_PTR: NonNull<()> = unsafe { mem::transmute((&raw const S).wrapping_add(4)) };
87+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
88+
|
89+
= 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.
90+
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
91+
HEX_DUMP
92+
}
93+
94+
error: aborting due to 9 previous errors
8495

8596
For more information about this error, try `rustc --explain E0080`.

tests/ui/consts/const-eval/ub-ref-ptr.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
55
//@ dont-require-annotations: NOTE
66
//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1"
7-
7+
#![feature(rustc_attrs)]
88
#![allow(invalid_value)]
99

1010
use std::mem;
@@ -65,5 +65,14 @@ const UNALIGNED_READ: () = unsafe {
6565
ptr.read(); //~ ERROR accessing memory
6666
};
6767

68+
// Check the general case of a pointer value not falling into the scalar valid range.
69+
#[rustc_layout_scalar_valid_range_start(1000)]
70+
pub struct High {
71+
pointer: *const (),
72+
}
73+
static S: u32 = 0; // just a static to construct a pointer with unknown absolute address
74+
const INVALID_VALUE_PTR: High = unsafe { mem::transmute(&S) };
75+
//~^ ERROR invalid value
76+
6877

6978
fn main() {}

tests/ui/consts/const-eval/ub-ref-ptr.stderr

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
103103
HEX_DUMP
104104
}
105105

106-
error[E0080]: reading memory at ALLOC3[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
106+
error[E0080]: reading memory at ALLOC4[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
107107
--> $DIR/ub-ref-ptr.rs:49:41
108108
|
109109
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
@@ -124,7 +124,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
124124
HEX_DUMP
125125
}
126126

127-
error[E0080]: reading memory at ALLOC4[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
127+
error[E0080]: reading memory at ALLOC5[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory
128128
--> $DIR/ub-ref-ptr.rs:54:38
129129
|
130130
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
162162
LL | ptr.read();
163163
| ^^^^^^^^^^ evaluation of `UNALIGNED_READ` failed here
164164

165-
error: aborting due to 15 previous errors
165+
error[E0080]: constructing invalid value: encountered a pointer with unknown absolute address, but expected something that is definitely greater or equal to 1000
166+
--> $DIR/ub-ref-ptr.rs:74:1
167+
|
168+
LL | const INVALID_VALUE_PTR: High = unsafe { mem::transmute(&S) };
169+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
170+
|
171+
= 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.
172+
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
173+
HEX_DUMP
174+
}
175+
176+
error: aborting due to 16 previous errors
166177

167178
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)