about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-09-22 19:46:30 +0200
committerRalf Jung <post@ralfj.de>2025-09-24 13:34:33 +0200
commit0a41add6293d76b165968d70f95e7edbbe65fe11 (patch)
treea5e1f7348bc38eb75193d44df1fe7ba8a02e9187
parent29005cb128e6d447e6bd9c110c9a684665f95985 (diff)
downloadrust-0a41add6293d76b165968d70f95e7edbbe65fe11.tar.gz
rust-0a41add6293d76b165968d70f95e7edbbe65fe11.zip
const-eval: improve and actually test the errors when pointers might be outside the range of a scalar
-rw-r--r--compiler/rustc_const_eval/messages.ftl4
-rw-r--r--compiler/rustc_const_eval/src/errors.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs5
-rw-r--r--tests/ui/consts/const-eval/ub-nonnull.rs4
-rw-r--r--tests/ui/consts/const-eval/ub-nonnull.stderr17
-rw-r--r--tests/ui/consts/const-eval/ub-ref-ptr.rs11
-rw-r--r--tests/ui/consts/const-eval/ub-ref-ptr.stderr17
8 files changed, 49 insertions, 21 deletions
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 700d7c26752..97674aea540 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -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})
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 2d412ee5ec2..29bddd59ffd 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -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 { .. }
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 9adc3fa4631..8648b83b8dc 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -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(());
                     }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 7c72a8ec243..1a9ae4bbceb 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -499,10 +499,7 @@ pub enum ValidationErrorKind<'tcx> {
     MutableRefInConst,
     NullFnPtr,
     NeverVal,
-    NullablePtrOutOfRange {
-        range: WrappingRange,
-        max_value: u128,
-    },
+    NonnullPtrMaybeNull,
     PtrOutOfRange {
         range: WrappingRange,
         max_value: u128,
diff --git a/tests/ui/consts/const-eval/ub-nonnull.rs b/tests/ui/consts/const-eval/ub-nonnull.rs
index 91646842624..851f3996cd1 100644
--- a/tests/ui/consts/const-eval/ub-nonnull.rs
+++ b/tests/ui/consts/const-eval/ub-nonnull.rs
@@ -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() {}
diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr
index 91c82efbc5e..e4486e3c500 100644
--- a/tests/ui/consts/const-eval/ub-nonnull.stderr
+++ b/tests/ui/consts/const-eval/ub-nonnull.stderr
@@ -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`.
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs
index d8e5102fcbe..5ff9748af0c 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.rs
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs
@@ -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() {}
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index c45f66c2925..9170cde94e2 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -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`.