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);
@@ -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 };
12791293 let src_alloc = self.get_alloc_raw(src_alloc_id)?;
12801294 let 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");
12821296 M::before_memory_read(
12831297 tcx,
12841298 &self.machine,
0 commit comments