diff options
| author | Ralf Jung <post@ralfj.de> | 2024-09-26 16:48:32 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-09-30 08:37:00 +0200 |
| commit | 4b8a5bd511814ed97640c46ab2232acc0e0ade41 (patch) | |
| tree | d364a1b02c32b5bc7a0b89b9ab92fd56bb8c52e7 /compiler/rustc_const_eval | |
| parent | e9df22f51d2f0f062d0beb83a28c8c76883d2ceb (diff) | |
panic when an interpreter error gets unintentionally discarded
Diffstat (limited to 'compiler/rustc_const_eval')
3 files changed, 37 insertions, 24 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 32f90254a94..05264d32c6b 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -13,9 +13,9 @@ use rustc_target::abi::{Abi, Align, HasDataLayout, Size}; use tracing::{instrument, trace}; use super::{ - AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, ImmTy, Immediate, InterpCx, InterpResult, - Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, Projectable, Provenance, - Scalar, alloc_range, mir_assign_valid_types, + AllocRef, AllocRefMut, CheckAlignMsg, CtfeProvenance, DiscardInterpError, ImmTy, Immediate, + InterpCx, InterpResult, Machine, MemoryKind, Misalignment, OffsetMode, OpTy, Operand, Pointer, + Projectable, Provenance, Scalar, alloc_range, mir_assign_valid_types, }; #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] @@ -490,9 +490,16 @@ where // If an access is both OOB and misaligned, we want to see the bounds error. // However we have to call `check_misalign` first to make the borrow checker happy. let misalign_err = self.check_misalign(mplace.mplace.misaligned, CheckAlignMsg::BasedOn); - let a = self.get_ptr_alloc_mut(mplace.ptr(), size)?; - misalign_err?; - Ok(a) + match self.get_ptr_alloc_mut(mplace.ptr(), size) { + Ok(a) => { + misalign_err?; + Ok(a) + } + Err(e) => { + misalign_err.discard_interp_err(); + Err(e) + } + } } /// Turn a local in the current frame into a place. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 203cceccd9d..3c9fdd73100 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -17,8 +17,8 @@ use rustc_hir as hir; use rustc_middle::bug; use rustc_middle::mir::interpret::ValidationErrorKind::{self, *}; use rustc_middle::mir::interpret::{ - ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance, - UnsupportedOpInfo, ValidationErrorInfo, alloc_range, + ExpectedKind, InterpError, InterpErrorInfo, InvalidMetaKind, Misalignment, PointerKind, + Provenance, UnsupportedOpInfo, ValidationErrorInfo, alloc_range, }; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; @@ -95,16 +95,19 @@ macro_rules! try_validation { Ok(x) => x, // We catch the error and turn it into a validation failure. We are okay with // allocation here as this can only slow down builds that fail anyway. - Err(e) => match e.kind() { - $( - $($p)|+ => - throw_validation_failure!( - $where, - $kind - ) - ),+, - #[allow(unreachable_patterns)] - _ => Err::<!, _>(e)?, + Err(e) => { + let (kind, backtrace) = e.into_parts(); + match kind { + $( + $($p)|+ => { + throw_validation_failure!( + $where, + $kind + ) + } + ),+, + _ => Err::<!, _>(InterpErrorInfo::from_parts(kind, backtrace))?, + } } } }}; @@ -510,7 +513,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance { ptr_kind, // FIXME this says "null pointer" when null but we need translate - pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(*i)) + pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i)) }, Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds { ptr_kind @@ -1231,7 +1234,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, Err(err) => { // For some errors we might be able to provide extra information. // (This custom logic does not fit the `try_validation!` macro.) - match err.kind() { + let (kind, backtrace) = err.into_parts(); + match kind { Ub(InvalidUninitBytes(Some((_alloc_id, access)))) | Unsup(ReadPointerAsInt(Some((_alloc_id, access)))) => { // Some byte was uninitialized, determine which // element that byte belongs to so we can @@ -1242,7 +1246,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, .unwrap(); self.path.push(PathElem::ArrayElem(i)); - if matches!(err.kind(), Ub(InvalidUninitBytes(_))) { + if matches!(kind, Ub(InvalidUninitBytes(_))) { throw_validation_failure!(self.path, Uninit { expected }) } else { throw_validation_failure!(self.path, PointerAsInt { expected }) @@ -1250,7 +1254,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } // Propagate upwards (that will also check for unexpected errors). - _ => return Err(err), + _ => return Err(InterpErrorInfo::from_parts(kind, backtrace)), } } } @@ -1282,7 +1286,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // It's not great to catch errors here, since we can't give a very good path, // but it's better than ICEing. Ub(InvalidVTableTrait { vtable_dyn_type, expected_dyn_type }) => { - InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type: *expected_dyn_type } + InvalidMetaWrongTrait { vtable_dyn_type, expected_dyn_type } }, ); } diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 19393188c9a..421648d9e7b 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -1,4 +1,5 @@ use rustc_middle::bug; +use rustc_middle::mir::interpret::DiscardInterpError; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; @@ -75,7 +76,8 @@ fn check_validity_requirement_strict<'tcx>( /*recursive*/ false, /*reset_provenance_and_padding*/ false, ) - .is_ok()) + .discard_interp_err() + .is_some()) } /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that |
