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> {
145144 alloc_map : M :: MemoryMap :: default ( ) ,
146145 extra_fn_ptr_map : FxIndexMap :: default ( ) ,
147146 dead_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 {
686685 if let Ok ( ( alloc_id, ..) ) = self . ptr_try_get_alloc_id ( ptr, size_i64) {
687686 M :: before_alloc_read ( self , alloc_id) ?;
688687 }
689688 }
690689
691690 if let Some ( ( alloc_id, offset, prov, alloc) ) = ptr_and_alloc {
692691 let range = alloc_range ( offset, size) ;
693- if !self . memory . validation_in_progress . get ( ) {
692+ if !self . memory . validation_in_progress {
694693 M :: before_memory_read (
695694 self . tcx ,
696695 & self . machine ,
@@ -766,11 +765,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
766765 let parts = self . get_ptr_access ( ptr, size) ?;
767766 if let Some ( ( alloc_id, offset, prov) ) = parts {
768767 let 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`.
771771 let ( alloc, machine) = self . get_alloc_raw_mut ( alloc_id) ?;
772772 let 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+ }
774776 Ok ( Some ( AllocRefMut { alloc, range, tcx : * tcx, alloc_id } ) )
775777 } else {
776778 Ok ( 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)`.
10201022 assert ! (
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 ) ;
10251027 assert ! (
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 >
11161118 AllocRefMut < ' 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.
11191125 pub fn write_scalar ( & mut self , range : AllocRange , val : Scalar < Prov > ) -> InterpResult < ' tcx > {
11201126 let range = self . range . subrange ( range) ;
@@ -1130,13 +1136,30 @@ impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
11301136 self . write_scalar ( alloc_range ( offset, self . tcx . data_layout ( ) . pointer_size ) , val)
11311137 }
11321138
1139+ /// Mark the given sub-range (relative to this allocation reference) as uninitialized.
1140+ pub fn write_uninit ( & mut self , range : AllocRange ) -> InterpResult < ' tcx > {
1141+ let range = self . range . subrange ( range) ;
1142+ Ok ( self
1143+ . alloc
1144+ . write_uninit ( & self . tcx , range)
1145+ . map_err ( |e| e. to_interp_error ( self . alloc_id ) ) ?)
1146+ }
1147+
11331148 /// Mark the entire referenced range as uninitialized
1134- pub fn write_uninit ( & mut self ) -> InterpResult < ' tcx > {
1149+ pub fn write_uninit_full ( & mut self ) -> InterpResult < ' tcx > {
11351150 Ok ( self
11361151 . alloc
11371152 . write_uninit ( & self . tcx , self . range )
11381153 . map_err ( |e| e. to_interp_error ( self . alloc_id ) ) ?)
11391154 }
1155+
1156+ /// Remove all provenance in the reference range.
1157+ pub fn clear_provenance ( & mut self ) -> InterpResult < ' tcx > {
1158+ Ok ( self
1159+ . alloc
1160+ . clear_provenance ( & self . tcx , self . range )
1161+ . map_err ( |e| e. to_interp_error ( self . alloc_id ) ) ?)
1162+ }
11401163}
11411164
11421165impl < ' tcx , ' a , Prov : Provenance , Extra , Bytes : AllocBytes > AllocRef < ' a , ' tcx , Prov , Extra , Bytes > {
@@ -1278,7 +1301,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
12781301 } ;
12791302 let src_alloc = self . get_alloc_raw ( src_alloc_id) ?;
12801303 let src_range = alloc_range ( src_offset, size) ;
1281- assert ! ( !self . memory. validation_in_progress. get ( ) , "we can't be copying during validation" ) ;
1304+ assert ! ( !self . memory. validation_in_progress, "we can't be copying during validation" ) ;
12821305 M :: before_memory_read (
12831306 tcx,
12841307 & self . machine ,
0 commit comments