Skip to content

Commit 8998c7a

Browse files
committed
try_validation: handle multi-branching, and use macro for most remaining manual throw_validation_failure sites
1 parent 7c44226 commit 8998c7a

File tree

2 files changed

+47
-78
lines changed

2 files changed

+47
-78
lines changed

src/librustc_mir/interpret/traits.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
149149
if args.len() != 1 {
150150
throw_ub!(InvalidDropFn(fn_sig));
151151
}
152-
let ty = args[0]
153-
.builtin_deref(true)
154-
.ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?
155-
.ty;
152+
let ty = args[0].builtin_deref(true).ok_or_else(|| err_ub!(InvalidDropFn(fn_sig)))?.ty;
156153
Ok((drop_instance, ty))
157154
}
158155

src/librustc_mir/interpret/validity.rs

+46-74
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,18 @@ macro_rules! throw_validation_failure {
7373
///
7474
macro_rules! try_validation {
7575
($e:expr, $where:expr,
76-
$( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? $( , )?
76+
$( $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
7777
) => {{
7878
match $e {
7979
Ok(x) => x,
8080
// We catch the error and turn it into a validation failure. We are okay with
8181
// allocation here as this can only slow down builds that fail anyway.
82-
$( Err(InterpErrorInfo { kind: $p, .. }) )|+ =>
82+
$( $( Err(InterpErrorInfo { kind: $p, .. }) )|+ =>
8383
throw_validation_failure!(
8484
$where,
8585
{ $( $what_fmt ),+ } $( expected { $( $expected_fmt ),+ } )?
8686
),
87+
)+
8788
#[allow(unreachable_patterns)]
8889
Err(e) => Err::<!, _>(e)?,
8990
}
@@ -367,66 +368,45 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
367368
self.check_wide_ptr_meta(place.meta, place.layout)?;
368369
}
369370
// Make sure this is dereferenceable and all.
370-
let size_and_align = match self.ecx.size_and_align_of(place.meta, place.layout) {
371-
Ok(res) => res,
372-
Err(err) => match err.kind {
373-
err_ub!(InvalidMeta(msg)) => throw_validation_failure!(self.path,
374-
{ "invalid {} metadata: {}", kind, msg }
375-
),
376-
_ => bug!("unexpected error during ptr size_and_align_of: {}", err),
377-
},
378-
};
371+
let size_and_align = try_validation!(
372+
self.ecx.size_and_align_of(place.meta, place.layout),
373+
self.path,
374+
err_ub!(InvalidMeta(msg)) => { "invalid {} metadata: {}", kind, msg },
375+
);
379376
let (size, align) = size_and_align
380377
// for the purpose of validity, consider foreign types to have
381378
// alignment and size determined by the layout (size will be 0,
382379
// alignment should take attributes into account).
383380
.unwrap_or_else(|| (place.layout.size, place.layout.align.abi));
384381
// Direct call to `check_ptr_access_align` checks alignment even on CTFE machines.
385-
let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align(
386-
place.ptr,
387-
size,
388-
Some(align),
389-
CheckInAllocMsg::InboundsTest,
390-
) {
391-
Ok(ptr) => ptr,
392-
Err(err) => {
393-
info!(
394-
"{:?} did not pass access check for size {:?}, align {:?}",
395-
place.ptr, size, align
396-
);
397-
match err.kind {
398-
err_ub!(DanglingIntPointer(0, _)) => {
399-
throw_validation_failure!(self.path,
400-
{ "a NULL {}", kind }
401-
)
402-
}
403-
err_ub!(DanglingIntPointer(i, _)) => throw_validation_failure!(self.path,
404-
{ "a {} to unallocated address {}", kind, i }
405-
),
406-
err_ub!(AlignmentCheckFailed { required, has }) => throw_validation_failure!(
407-
self.path,
408-
{
409-
"an unaligned {} (required {} byte alignment but found {})",
410-
kind,
411-
required.bytes(),
412-
has.bytes()
413-
}
414-
),
415-
err_unsup!(ReadBytesAsPointer) => throw_validation_failure!(self.path,
416-
{ "a dangling {} (created from integer)", kind }
417-
),
418-
err_ub!(PointerOutOfBounds { .. }) => throw_validation_failure!(self.path,
419-
{ "a dangling {} (going beyond the bounds of its allocation)", kind }
420-
),
421-
// This cannot happen during const-eval (because interning already detects
422-
// dangling pointers), but it can happen in Miri.
423-
err_ub!(PointerUseAfterFree(_)) => throw_validation_failure!(self.path,
424-
{ "a dangling {} (use-after-free)", kind }
425-
),
426-
_ => bug!("Unexpected error during ptr inbounds test: {}", err),
427-
}
428-
}
429-
};
382+
let ptr: Option<_> = try_validation!(
383+
self.ecx.memory.check_ptr_access_align(
384+
place.ptr,
385+
size,
386+
Some(align),
387+
CheckInAllocMsg::InboundsTest,
388+
),
389+
self.path,
390+
err_ub!(DanglingIntPointer(0, _)) =>
391+
{ "a NULL {}", kind },
392+
err_ub!(DanglingIntPointer(i, _)) =>
393+
{ "a {} to unallocated address {}", kind, i },
394+
err_ub!(AlignmentCheckFailed { required, has }) =>
395+
{
396+
"an unaligned {} (required {} byte alignment but found {})",
397+
kind,
398+
required.bytes(),
399+
has.bytes()
400+
},
401+
err_unsup!(ReadBytesAsPointer) =>
402+
{ "a dangling {} (created from integer)", kind },
403+
err_ub!(PointerOutOfBounds { .. }) =>
404+
{ "a dangling {} (going beyond the bounds of its allocation)", kind },
405+
// This cannot happen during const-eval (because interning already detects
406+
// dangling pointers), but it can happen in Miri.
407+
err_ub!(PointerUseAfterFree(_)) =>
408+
{ "a dangling {} (use-after-free)", kind },
409+
);
430410
// Recursive checking
431411
if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts {
432412
if let Some(ptr) = ptr {
@@ -710,23 +690,14 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
710690
assert!(op.layout.ty.builtin_deref(true).is_none());
711691

712692
// Recursively walk the type. Translate some possible errors to something nicer.
713-
match self.walk_value(op) {
714-
Ok(()) => {}
715-
Err(err) => match err.kind {
716-
err_ub!(InvalidDiscriminant(val)) => {
717-
throw_validation_failure!(self.path,
718-
{ "{}", val } expected { "a valid enum discriminant" }
719-
)
720-
}
721-
err_unsup!(ReadPointerAsBytes) => {
722-
throw_validation_failure!(self.path,
723-
{ "a pointer" } expected { "plain (non-pointer) bytes" }
724-
)
725-
}
726-
// Propagate upwards (that will also check for unexpected errors).
727-
_ => return Err(err),
728-
},
729-
}
693+
try_validation!(
694+
self.walk_value(op),
695+
self.path,
696+
err_ub!(InvalidDiscriminant(val)) =>
697+
{ "{}", val } expected { "a valid enum discriminant" },
698+
err_unsup!(ReadPointerAsBytes) =>
699+
{ "a pointer" } expected { "plain (non-pointer) bytes" },
700+
);
730701

731702
// *After* all of this, check the ABI. We need to check the ABI to handle
732703
// types like `NonNull` where the `Scalar` info is more restrictive than what
@@ -825,7 +796,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
825796
Ok(()) => {}
826797
// Some error happened, try to provide a more detailed description.
827798
Err(err) => {
828-
// For some errors we might be able to provide extra information
799+
// For some errors we might be able to provide extra information.
800+
// (This custom logic does not fit the `try_validation!` macro.)
829801
match err.kind {
830802
err_ub!(InvalidUndefBytes(Some(ptr))) => {
831803
// Some byte was uninitialized, determine which

0 commit comments

Comments
 (0)