88
99use std:: assert_matches:: assert_matches;
1010use std:: borrow:: Cow ;
11- use std:: cell:: Cell ;
1211use std:: collections:: VecDeque ;
13- use std:: { fmt, ptr} ;
12+ use std:: { fmt, mem , ptr} ;
1413
1514use rustc_ast:: Mutability ;
1615use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
@@ -118,7 +117,7 @@ pub struct Memory<'tcx, M: Machine<'tcx>> {
118117/// This stores whether we are currently doing reads purely for the purpose of validation.
119118/// Those reads do not trigger the machine's hooks for memory reads.
120119/// Needless to say, this must only be set with great care!
121- validation_in_progress : Cell < bool > ,
120+ validation_in_progress : bool ,
122121}
123122
124123/// A reference to some allocation that was already bounds-checked for the given region
@@ -145,7 +144,7 @@ impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
145144alloc_map : M :: MemoryMap :: default ( ) ,
146145extra_fn_ptr_map : FxIndexMap :: default ( ) ,
147146dead_alloc_map : FxIndexMap :: default ( ) ,
148- validation_in_progress : Cell :: new ( false ) ,
147+ validation_in_progress : false ,
149148}
150149}
151150
@@ -682,15 +681,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
682681// We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
683682// accesses. That means we cannot rely on the closure above or the `Some` branch below. We
684683// do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
685- if !self . memory . validation_in_progress . get ( ) {
684+ if !self . memory . validation_in_progress {
686685if let Ok ( ( alloc_id, ..) ) = self . ptr_try_get_alloc_id ( ptr, size_i64) {
687686M :: before_alloc_read ( self , alloc_id) ?;
688687}
689688}
690689
691690if let Some ( ( alloc_id, offset, prov, alloc) ) = ptr_and_alloc {
692691let range = alloc_range ( offset, size) ;
693- if !self . memory . validation_in_progress . get ( ) {
692+ if !self . memory . validation_in_progress {
694693M :: before_memory_read (
695694self . tcx ,
696695& self . machine ,
@@ -766,11 +765,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
766765let parts = self . get_ptr_access ( ptr, size) ?;
767766if let Some ( ( alloc_id, offset, prov) ) = parts {
768767let tcx = self . tcx ;
768+ let validation_in_progress = self . memory . validation_in_progress ;
769769// FIXME: can we somehow avoid looking up the allocation twice here?
770770// We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
771771let ( alloc, machine) = self . get_alloc_raw_mut ( alloc_id) ?;
772772let range = alloc_range ( offset, size) ;
773- M :: before_memory_write ( tcx, machine, & mut alloc. extra , ( alloc_id, prov) , range) ?;
773+ if !validation_in_progress {
774+ M :: before_memory_write ( tcx, machine, & mut alloc. extra , ( alloc_id, prov) , range) ?;
775+ }
774776Ok ( Some ( AllocRefMut { alloc, range, tcx : * tcx, alloc_id } ) )
775777} else {
776778Ok ( None )
@@ -1014,16 +1016,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10141016///
10151017/// We do this so Miri's allocation access tracking does not show the validation
10161018/// reads as spurious accesses.
1017- pub fn run_for_validation < R > ( & self , f : impl FnOnce ( ) -> R ) -> R {
1019+ pub fn run_for_validation < R > ( & mut self , f : impl FnOnce ( & mut Self ) -> R ) -> R {
10181020// This deliberately uses `==` on `bool` to follow the pattern
10191021// `assert!(val.replace(new) == old)`.
10201022assert ! (
1021- self . memory. validation_in_progress. replace ( true ) == false ,
1023+ mem :: replace ( & mut self . memory. validation_in_progress, true ) == false ,
10221024"`validation_in_progress` was already set"
10231025) ;
1024- let res = f ( ) ;
1026+ let res = f ( self ) ;
10251027assert ! (
1026- self . memory. validation_in_progress. replace ( false ) == true ,
1028+ mem :: replace ( & mut self . memory. validation_in_progress, false ) == true ,
10271029"`validation_in_progress` was unset by someone else"
10281030) ;
10291031 res
@@ -1115,6 +1117,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
11151117impl < ' tcx , ' a , Prov : Provenance , Extra , Bytes : AllocBytes >
11161118AllocRefMut < ' a , ' tcx , Prov , Extra , Bytes >
11171119{
1120+ pub fn as_ref < ' b > ( & ' b self ) -> AllocRef < ' b , ' tcx , Prov , Extra , Bytes > {
1121+ AllocRef { alloc : self . alloc , range : self . range , tcx : self . tcx , alloc_id : self . alloc_id }
1122+ }
1123+
11181124/// `range` is relative to this allocation reference, not the base of the allocation.
11191125pub fn write_scalar ( & mut self , range : AllocRange , val : Scalar < Prov > ) -> InterpResult < ' tcx > {
11201126let range = self . range . subrange ( range) ;
@@ -1137,6 +1143,14 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
11371143. write_uninit ( & self . tcx , self . range )
11381144. map_err ( |e| e. to_interp_error ( self . alloc_id ) ) ?)
11391145}
1146+
1147+ /// Remove all provenance in the reference range.
1148+ pub fn clear_provenance ( & mut self ) -> InterpResult < ' tcx > {
1149+ Ok ( self
1150+ . alloc
1151+ . clear_provenance ( & self . tcx , self . range )
1152+ . map_err ( |e| e. to_interp_error ( self . alloc_id ) ) ?)
1153+ }
11401154}
11411155
11421156impl < ' tcx , ' a , Prov : Provenance , Extra , Bytes : AllocBytes > AllocRef < ' a , ' tcx , Prov , Extra , Bytes > {
@@ -1278,7 +1292,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
12781292} ;
12791293let src_alloc = self . get_alloc_raw ( src_alloc_id) ?;
12801294let src_range = alloc_range ( src_offset, size) ;
1281- assert ! ( !self . memory. validation_in_progress. get ( ) , "we can't be copying during validation" ) ;
1295+ assert ! ( !self . memory. validation_in_progress, "we can't be copying during validation" ) ;
12821296M :: before_memory_read (
12831297 tcx,
12841298& self . machine ,
0 commit comments