miri: Detect uninitialized integers and floats
Change the Miri engine to allow configuring whether to check initialization of integers and floats. This allows the Miri tool to optionally check for initialization if requested by the user.
This commit is contained in:
parent
00d5e42e77
commit
d8a1454dd8
2 changed files with 12 additions and 5 deletions
|
@ -131,6 +131,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||||
/// Whether to enforce the validity invariant
|
/// Whether to enforce the validity invariant
|
||||||
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
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.
|
/// Whether function calls should be [ABI](Abi)-checked.
|
||||||
fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
fn enforce_abi(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
|
||||||
true
|
true
|
||||||
|
@ -426,6 +430,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||||
false // for now, we don't enforce validity
|
false // for now, we don't enforce validity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn enforce_number_validity(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn call_extra_fn(
|
fn call_extra_fn(
|
||||||
_ecx: &mut InterpCx<$mir, $tcx, Self>,
|
_ecx: &mut InterpCx<$mir, $tcx, Self>,
|
||||||
|
|
|
@ -520,7 +520,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
let value = self.read_scalar(value)?;
|
let value = self.read_scalar(value)?;
|
||||||
// NOTE: Keep this in sync with the array optimization for int/float
|
// NOTE: Keep this in sync with the array optimization for int/float
|
||||||
// types below!
|
// 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
|
// 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());
|
let is_bits = value.check_init().map_or(false, |v| v.try_to_int().is_ok());
|
||||||
if !is_bits {
|
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" }
|
{ "{}", 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)
|
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(
|
match alloc.check_bytes(
|
||||||
alloc_range(Size::ZERO, size),
|
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.
|
// In the happy case, we needn't check anything else.
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue