validation should only catch UB errors
This commit is contained in:
parent
cf2c65b251
commit
1a1220c5e4
1 changed files with 20 additions and 17 deletions
|
@ -19,6 +19,8 @@ use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, Wr
|
||||||
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
// for the validation errors
|
||||||
|
use super::UndefinedBehaviorInfo::*;
|
||||||
use super::{
|
use super::{
|
||||||
CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine,
|
CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine,
|
||||||
MemPlaceMeta, OpTy, Scalar, ValueVisitor,
|
MemPlaceMeta, OpTy, Scalar, ValueVisitor,
|
||||||
|
@ -59,6 +61,7 @@ macro_rules! throw_validation_failure {
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// The patterns must be of type `UndefinedBehaviorInfo`.
|
||||||
/// An additional expected parameter can also be added to the failure message:
|
/// An additional expected parameter can also be added to the failure message:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -86,7 +89,7 @@ macro_rules! try_validation {
|
||||||
// allocation here as this can only slow down builds that fail anyway.
|
// allocation here as this can only slow down builds that fail anyway.
|
||||||
Err(e) => match e.kind() {
|
Err(e) => match e.kind() {
|
||||||
$(
|
$(
|
||||||
$($p)|+ =>
|
InterpError::UndefinedBehavior($($p)|+) =>
|
||||||
throw_validation_failure!(
|
throw_validation_failure!(
|
||||||
$where,
|
$where,
|
||||||
{ $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )?
|
{ $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )?
|
||||||
|
@ -312,7 +315,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
Ok(try_validation!(
|
Ok(try_validation!(
|
||||||
self.ecx.read_immediate(op),
|
self.ecx.read_immediate(op),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(InvalidUninitBytes(None)) => { "uninitialized memory" } expected { "{expected}" }
|
InvalidUninitBytes(None) => { "uninitialized memory" } expected { "{expected}" }
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,8 +340,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
let (_ty, _trait) = try_validation!(
|
let (_ty, _trait) = try_validation!(
|
||||||
self.ecx.get_ptr_vtable(vtable),
|
self.ecx.get_ptr_vtable(vtable),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(DanglingIntPointer(..)) |
|
DanglingIntPointer(..) |
|
||||||
err_ub!(InvalidVTablePointer(..)) =>
|
InvalidVTablePointer(..) =>
|
||||||
{ "{vtable}" } expected { "a vtable pointer" },
|
{ "{vtable}" } expected { "a vtable pointer" },
|
||||||
);
|
);
|
||||||
// FIXME: check if the type/trait match what ty::Dynamic says?
|
// FIXME: check if the type/trait match what ty::Dynamic says?
|
||||||
|
@ -374,7 +377,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
let size_and_align = try_validation!(
|
let size_and_align = try_validation!(
|
||||||
self.ecx.size_and_align_of_mplace(&place),
|
self.ecx.size_and_align_of_mplace(&place),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(InvalidMeta(msg)) => { "invalid {} metadata: {}", kind, msg },
|
InvalidMeta(msg) => { "invalid {} metadata: {}", kind, msg },
|
||||||
);
|
);
|
||||||
let (size, align) = size_and_align
|
let (size, align) = size_and_align
|
||||||
// for the purpose of validity, consider foreign types to have
|
// for the purpose of validity, consider foreign types to have
|
||||||
|
@ -390,21 +393,21 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
|
CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
|
||||||
),
|
),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(AlignmentCheckFailed { required, has }) =>
|
AlignmentCheckFailed { required, has } =>
|
||||||
{
|
{
|
||||||
"an unaligned {kind} (required {} byte alignment but found {})",
|
"an unaligned {kind} (required {} byte alignment but found {})",
|
||||||
required.bytes(),
|
required.bytes(),
|
||||||
has.bytes()
|
has.bytes()
|
||||||
},
|
},
|
||||||
err_ub!(DanglingIntPointer(0, _)) =>
|
DanglingIntPointer(0, _) =>
|
||||||
{ "a null {kind}" },
|
{ "a null {kind}" },
|
||||||
err_ub!(DanglingIntPointer(i, _)) =>
|
DanglingIntPointer(i, _) =>
|
||||||
{ "a dangling {kind} (address {i:#x} is unallocated)" },
|
{ "a dangling {kind} (address {i:#x} is unallocated)" },
|
||||||
err_ub!(PointerOutOfBounds { .. }) =>
|
PointerOutOfBounds { .. } =>
|
||||||
{ "a dangling {kind} (going beyond the bounds of its allocation)" },
|
{ "a dangling {kind} (going beyond the bounds of its allocation)" },
|
||||||
// This cannot happen during const-eval (because interning already detects
|
// This cannot happen during const-eval (because interning already detects
|
||||||
// dangling pointers), but it can happen in Miri.
|
// dangling pointers), but it can happen in Miri.
|
||||||
err_ub!(PointerUseAfterFree(..)) =>
|
PointerUseAfterFree(..) =>
|
||||||
{ "a dangling {kind} (use-after-free)" },
|
{ "a dangling {kind} (use-after-free)" },
|
||||||
);
|
);
|
||||||
// Do not allow pointers to uninhabited types.
|
// Do not allow pointers to uninhabited types.
|
||||||
|
@ -475,7 +478,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
try_validation!(
|
try_validation!(
|
||||||
value.to_bool(),
|
value.to_bool(),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(InvalidBool(..)) =>
|
InvalidBool(..) =>
|
||||||
{ "{:x}", value } expected { "a boolean" },
|
{ "{:x}", value } expected { "a boolean" },
|
||||||
);
|
);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
@ -485,7 +488,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
try_validation!(
|
try_validation!(
|
||||||
value.to_char(),
|
value.to_char(),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(InvalidChar(..)) =>
|
InvalidChar(..) =>
|
||||||
{ "{:x}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" },
|
{ "{:x}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" },
|
||||||
);
|
);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
@ -544,8 +547,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||||
let _fn = try_validation!(
|
let _fn = try_validation!(
|
||||||
self.ecx.get_ptr_fn(ptr),
|
self.ecx.get_ptr_fn(ptr),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(DanglingIntPointer(..)) |
|
DanglingIntPointer(..) |
|
||||||
err_ub!(InvalidFunctionPointer(..)) =>
|
InvalidFunctionPointer(..) =>
|
||||||
{ "{ptr}" } expected { "a function pointer" },
|
{ "{ptr}" } expected { "a function pointer" },
|
||||||
);
|
);
|
||||||
// FIXME: Check if the signature matches
|
// FIXME: Check if the signature matches
|
||||||
|
@ -660,9 +663,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||||
Ok(try_validation!(
|
Ok(try_validation!(
|
||||||
this.ecx.read_discriminant(op),
|
this.ecx.read_discriminant(op),
|
||||||
this.path,
|
this.path,
|
||||||
err_ub!(InvalidTag(val)) =>
|
InvalidTag(val) =>
|
||||||
{ "{:x}", val } expected { "a valid enum tag" },
|
{ "{:x}", val } expected { "a valid enum tag" },
|
||||||
err_ub!(InvalidUninitBytes(None)) =>
|
InvalidUninitBytes(None) =>
|
||||||
{ "uninitialized bytes" } expected { "a valid enum tag" },
|
{ "uninitialized bytes" } expected { "a valid enum tag" },
|
||||||
)
|
)
|
||||||
.1)
|
.1)
|
||||||
|
@ -805,7 +808,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||||
try_validation!(
|
try_validation!(
|
||||||
self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)),
|
self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)),
|
||||||
self.path,
|
self.path,
|
||||||
err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" },
|
InvalidUninitBytes(..) => { "uninitialized data in `str`" },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ty::Array(tys, ..) | ty::Slice(tys)
|
ty::Array(tys, ..) | ty::Slice(tys)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue