Skip to content

Commit 8afb088

Browse files
committed
split up prepare_for_native_access + code review
1 parent 12d1261 commit 8afb088

File tree

3 files changed

+28
-10
lines changed

3 files changed

+28
-10
lines changed

compiler/rustc_middle/src/mir/interpret/allocation.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -796,8 +796,8 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
796796
Ok(())
797797
}
798798

799-
/// Initialize all previously uninitialized bytes in the entire allocation, and set
800-
/// provenance of everything to `Wildcard`. Before calling this, make sure all
799+
/// Initialize all previously uninitialized bytes in the entire allocation, but
800+
/// do not actually mark them as init. Before calling this, make sure all
801801
/// provenance in this allocation is exposed!
802802
pub fn prepare_for_native_access(&mut self) {
803803
let full_range = AllocRange { start: Size::ZERO, size: Size::from_bytes(self.len()) };
@@ -809,16 +809,19 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
809809
uninit_bytes.fill(0);
810810
}
811811
}
812-
self.mark_foreign_write(full_range);
813812
}
814813

815814
/// Mark all bytes in the given range as initialised and reset the provenance
816815
/// to wildcards. This entirely breaks the normal mechanisms for tracking
817816
/// initialisation and is only provided for Miri operating in native-lib
818817
/// mode. UB will be missed if the underlying bytes were not actually initialized.
819-
pub fn mark_foreign_write(&mut self, range: AllocRange) {
818+
///
819+
/// If `range` is `None`, defaults to performing this on the whole allocation.
820+
pub fn process_native_write(&mut self, cx: &impl HasDataLayout, range: Option<AllocRange>) {
821+
let range =
822+
range.unwrap_or(AllocRange { start: Size::ZERO, size: Size::from_bytes(self.len()) });
820823
self.mark_init(range, true);
821-
self.provenance.write_wildcards(range);
824+
self.provenance.write_wildcards(cx, range);
822825
}
823826

824827
/// Remove all provenance in the given memory range.

compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,21 +213,35 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
213213
}
214214

215215
/// Overwrites all provenance in the given range with wildcard provenance.
216+
/// Pointers partially overwritten will have their provenances
216217
///
217218
/// Provided for usage in Miri and panics otherwise.
218-
pub fn write_wildcards(&mut self, range: AllocRange) {
219+
pub fn write_wildcards(&mut self, cx: &impl HasDataLayout, range: AllocRange) {
219220
assert!(
220221
Prov::OFFSET_IS_ADDR,
221222
"writing wildcard provenance is not supported when `OFFSET_IS_ADDR` is false"
222223
);
223224
let wildcard = Prov::WILDCARD.unwrap();
224225

225-
// Remove all pointer provenances, then write wildcards into the whole byte range.
226-
self.ptrs.clear();
226+
// Get pointer provenances that overlap with the range, then remove them.
227+
let ptr_range = Self::adjusted_range_ptrs(range, cx);
228+
let removed = ptr_range.filter_map(|i| self.ptrs.remove(&i).map(|p| (i, p)));
229+
// Overwrite bytewise provenance.
227230
let bytes = self.bytes.get_or_insert_with(Box::default);
228-
for offset in range.start..range.start + range.size {
231+
for offset in range.start..range.end() {
229232
bytes.insert(offset, wildcard);
230233
}
234+
// Now readd pointer provenances that were only partly overwritten. Always
235+
// check both the start and end to allow for a write to happen in the middle
236+
// of a pointer.
237+
for (rm_ofs, prov) in removed {
238+
for head_ofs in rm_ofs..range.start {
239+
bytes.insert(head_ofs, prov);
240+
}
241+
for tail_ofs in range.end()..rm_ofs + cx.data_layout().pointer_size() {
242+
bytes.insert(tail_ofs, prov);
243+
}
244+
}
231245
}
232246
}
233247

src/tools/miri/src/shims/native_lib/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
251251

252252
// Prepare for possible write from native code if mutable.
253253
if info.mutbl.is_mut() {
254-
let alloc = &mut this.get_alloc_raw_mut(alloc_id)?.0;
254+
let (alloc, cx) = this.get_alloc_raw_mut(alloc_id)?;
255255
alloc.prepare_for_native_access();
256+
alloc.process_native_write(&cx.tcx, None);
256257
// Also expose *mutable* provenance for the interpreter-level allocation.
257258
std::hint::black_box(alloc.get_bytes_unchecked_raw_mut().expose_provenance());
258259
}

0 commit comments

Comments
 (0)