1
Fork 0

Rollup merge of #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 https://github.com/rust-lang/unsafe-code-guidelines/issues/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`
This commit is contained in:
Yuki Okushi 2022-05-18 07:41:01 +09:00 committed by GitHub
commit 248890c32e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 15 additions and 10 deletions

View file

@ -412,22 +412,27 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
self.path,
err_ub!(AlignmentCheckFailed { required, has }) =>
{
"an unaligned {} (required {} byte alignment but found {})",
kind,
"an unaligned {kind} (required {} byte alignment but found {})",
required.bytes(),
has.bytes()
},
err_ub!(DanglingIntPointer(0, _)) =>
{ "a null {}", kind },
{ "a null {kind}" },
err_ub!(DanglingIntPointer(i, _)) =>
{ "a dangling {} (address 0x{:x} is unallocated)", kind, i },
{ "a dangling {kind} (address 0x{i:x} is unallocated)" },
err_ub!(PointerOutOfBounds { .. }) =>
{ "a dangling {} (going beyond the bounds of its allocation)", kind },
{ "a dangling {kind} (going beyond the bounds of its allocation)" },
// This cannot happen during const-eval (because interning already detects
// dangling pointers), but it can happen in Miri.
err_ub!(PointerUseAfterFree(..)) =>
{ "a dangling {} (use-after-free)", kind },
{ "a dangling {kind} (use-after-free)" },
);
// Do not allow pointers to uninhabited types.
if place.layout.abi.is_uninhabited() {
throw_validation_failure!(self.path,
{ "a {kind} pointing to uninhabited type {}", place.layout.ty }
)
}
// Recursive checking
if let Some(ref mut ref_tracking) = self.ref_tracking {
// Proceed recursively even for ZST, no reason to skip them!