Auto merge of #88670 - camelid:miri-uninit-num, r=RalfJung

miri: Detect uninitialized integers and floats

Part of rust-lang/miri#1340.

Companion Miri PR: rust-lang/miri#1904

r? `@RalfJung`
This commit is contained in:
bors 2021-11-10 09:36:03 +00:00
commit 800a156c1e
2 changed files with 12 additions and 5 deletions

View file

@ -131,6 +131,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
/// Whether to enforce the validity invariant
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
/// Whether to enforce validity (e.g., initialization and not having ptr provenance)
/// of integers and floats.
fn enforce_number_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
/// Whether function calls should be [ABI](Abi)-checked.
fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
true
@ -426,6 +430,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
false // for now, we don't enforce validity
}
#[inline(always)]
fn enforce_number_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
true
}
#[inline(always)]
fn call_extra_fn(
_ecx: &mut InterpCx<$mir, $tcx, Self>,

View file

@ -520,7 +520,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
let value = self.read_scalar(value)?;
// NOTE: Keep this in sync with the array optimization for int/float
// types below!
if self.ctfe_mode.is_some() {
if M::enforce_number_validity(self.ecx) {
// Integers/floats in CTFE: Must be scalar bits, pointers are dangerous
let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok());
if !is_bits {
@ -528,9 +528,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
{ "{}", value } expected { "initialized plain (non-pointer) bytes" }
)
}
} else {
// At run-time, for now, we accept *anything* for these types, including
// uninit. We should fix that, but let's start low.
}
Ok(true)
}
@ -855,9 +852,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
}
};
let allow_uninit_and_ptr = !M::enforce_number_validity(self.ecx);
match alloc.check_bytes(
alloc_range(Size::ZERO, size),
/*allow_uninit_and_ptr*/ self.ctfe_mode.is_none(),
allow_uninit_and_ptr,
) {
// In the happy case, we needn't check anything else.
Ok(()) => {}