Skip to content

Commit 248890c

Browse files
authored
Rollup merge of rust-lang#97116 - RalfJung:ref-validity, r=oli-obk
interpret/validity: reject references to uninhabited types According to https://doc.rust-lang.org/reference/behavior-considered-undefined.html, this is definitely UB. And we can check this without actually looking up anything in memory, we just need the reference value and its type, making this a great candidate for a validity invariant IMO and my favorite resolution of rust-lang/unsafe-code-guidelines#77. With this PR, Miri with `-Zmiri-check-number-validity` implements all my preferred options for what the validity invariants of our types could be. :) CTFE has been doing recursive checking anyway, so this is backwards compatible but might change the error output. I will submit a PR with the new Miri tests soon. r? `@oli-obk`
2 parents b8dd270 + 201750d commit 248890c

File tree

5 files changed

+15
-10
lines changed

5 files changed

+15
-10
lines changed

compiler/rustc_const_eval/src/interpret/validity.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -412,22 +412,27 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
412412
self.path,
413413
err_ub!(AlignmentCheckFailed { required, has }) =>
414414
{
415-
"an unaligned {} (required {} byte alignment but found {})",
416-
kind,
415+
"an unaligned {kind} (required {} byte alignment but found {})",
417416
required.bytes(),
418417
has.bytes()
419418
},
420419
err_ub!(DanglingIntPointer(0, _)) =>
421-
{ "a null {}", kind },
420+
{ "a null {kind}" },
422421
err_ub!(DanglingIntPointer(i, _)) =>
423-
{ "a dangling {} (address 0x{:x} is unallocated)", kind, i },
422+
{ "a dangling {kind} (address 0x{i:x} is unallocated)" },
424423
err_ub!(PointerOutOfBounds { .. }) =>
425-
{ "a dangling {} (going beyond the bounds of its allocation)", kind },
424+
{ "a dangling {kind} (going beyond the bounds of its allocation)" },
426425
// This cannot happen during const-eval (because interning already detects
427426
// dangling pointers), but it can happen in Miri.
428427
err_ub!(PointerUseAfterFree(..)) =>
429-
{ "a dangling {} (use-after-free)", kind },
428+
{ "a dangling {kind} (use-after-free)" },
430429
);
430+
// Do not allow pointers to uninhabited types.
431+
if place.layout.abi.is_uninhabited() {
432+
throw_validation_failure!(self.path,
433+
{ "a {kind} pointing to uninhabited type {}", place.layout.ty }
434+
)
435+
}
431436
// Recursive checking
432437
if let Some(ref mut ref_tracking) = self.ref_tracking {
433438
// Proceed recursively even for ZST, no reason to skip them!

src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value
1111
--> $DIR/ub-uninhabit.rs:18:1
1212
|
1313
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a value of uninhabited type Bar
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type Bar
1515
|
1616
= 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.
1717
= note: the raw bytes of the constant (size: 4, align: 4) {

src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ error[E0080]: it is undefined behavior to use this value
1111
--> $DIR/ub-uninhabit.rs:18:1
1212
|
1313
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>: encountered a value of uninhabited type Bar
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type Bar
1515
|
1616
= 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.
1717
= note: the raw bytes of the constant (size: 8, align: 8) {

src/test/ui/consts/validate_never_arrays.32bit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/validate_never_arrays.rs:4:1
33
|
44
LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type [!; 1]
66
|
77
= 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.
88
= note: the raw bytes of the constant (size: 4, align: 4) {

src/test/ui/consts/validate_never_arrays.64bit.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
22
--> $DIR/validate_never_arrays.rs:4:1
33
|
44
LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered a value of the never type `!`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to uninhabited type [!; 1]
66
|
77
= 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.
88
= note: the raw bytes of the constant (size: 8, align: 8) {

0 commit comments

Comments
 (0)