From 5f680443579ae914c005cc40485a1c029cbe4cdc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Mar 2026 18:37:52 +0100 Subject: [PATCH] miri recursive checking: only check one layer deep --- .../rustc_const_eval/src/interpret/validity.rs | 14 +++++++++++--- src/tools/miri/README.md | 5 +++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 62ee653000dc..9310cda8450b 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1512,6 +1512,7 @@ fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'t } impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { + /// The internal core entry point for all validation operations. fn validate_operand_internal( &mut self, val: &PlaceTy<'tcx, M::Provenance>, @@ -1519,6 +1520,7 @@ fn validate_operand_internal( ref_tracking: Option<&mut RefTracking, Vec>>, ctfe_mode: Option, reset_provenance_and_padding: bool, + start_in_may_dangle: bool, ) -> InterpResult<'tcx> { trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); @@ -1536,7 +1538,7 @@ fn validate_operand_internal( ecx, reset_provenance_and_padding, data_bytes: reset_padding.then_some(RangeSet(Vec::new())), - may_dangle: false, + may_dangle: start_in_may_dangle, }; v.visit_value(val)?; v.reset_padding(val)?; @@ -1579,6 +1581,7 @@ pub(crate) fn const_validate_operand( Some(ref_tracking), Some(ctfe_mode), /*reset_provenance*/ false, + /*start_in_may_dangle*/ false, ) } @@ -1610,6 +1613,7 @@ pub fn validate_operand( None, None, reset_provenance_and_padding, + /*start_in_may_dangle*/ false, ); } // Do a recursive check. @@ -1620,15 +1624,19 @@ pub fn validate_operand( Some(&mut ref_tracking), None, reset_provenance_and_padding, + /*start_in_may_dangle*/ false, )?; while let Some((mplace, path)) = ref_tracking.todo.pop() { - // Things behind reference do *not* have the provenance reset. + // Things behind reference do *not* have the provenance reset. In fact + // we treat the entire thing as being inside MaybeDangling, i.e., references + // do not have to be dereferenceable. self.validate_operand_internal( &mplace.into(), path, - Some(&mut ref_tracking), + None, // no further recursion None, /*reset_provenance_and_padding*/ false, + /*start_in_may_dangle*/ true, )?; } interp_ok(()) diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md index 97f385ad755b..f51cd96486b4 100644 --- a/src/tools/miri/README.md +++ b/src/tools/miri/README.md @@ -476,8 +476,9 @@ to Miri failing to detect cases of undefined behavior in a program. but reports to the program that it did actually write. This is useful when you are not interested in the actual program's output, but only want to see Miri's errors and warnings. -* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking - recurse below references. +* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking recurse + *one level* below references. The in-memory value is treated as-if it was inside a + `MaybeDangling`, i.e., nested references do not even have to be dereferenceable. * `-Zmiri-preemption-rate` configures the probability that at the end of a basic block, the active thread will be preempted. The default is `0.01` (i.e., 1%). Setting this to `0` disables preemption. Note that even without preemption, the schedule is still non-deterministic: