Skip to content

Commit 3e1f928

Browse files
committed
uncertain: allow accesses to span multiple allocs
1 parent 3d16495 commit 3e1f928

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#![feature(unqualified_local_imports)]
1616
#![feature(derive_coerce_pointee)]
1717
#![feature(arbitrary_self_types)]
18+
#![feature(iter_advance_by)]
1819
// Configure clippy and other lints
1920
#![allow(
2021
clippy::collapsible_else_if,

src/shims/native_lib/mod.rs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -227,29 +227,38 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
227227

228228
for evt in events.acc_events {
229229
let evt_rg = evt.get_range();
230-
// We're assuming an access only touches 1 allocation.
231-
let alloc_id = this
232-
.alloc_id_from_addr(evt_rg.addr.to_u64(), evt_rg.size.try_into().unwrap(), true)
233-
.expect("Foreign code did an out-of-bounds access!");
234230

235-
let alloc = this.get_alloc_raw(alloc_id)?;
236-
let alloc_addr = alloc.get_bytes_unchecked_raw().addr();
237-
238-
// Shift the overlap range to be an offset from the allocation base addr.
239-
let overlap = evt_rg.addr.strict_sub(alloc_addr)..evt_rg.end().strict_sub(alloc_addr);
240-
241-
// Reads are infallible, writes might not be.
242-
if evt.is_read() {
243-
let p_map = alloc.provenance();
244-
for idx in overlap {
245-
// If a provenance was read by the foreign code, expose it.
246-
if let Some(prov) = p_map.get(Size::from_bytes(idx), this) {
247-
this.expose_provenance(prov)?;
231+
// LLVM at least permits vectorising accesses to adjacent allocations,
232+
// so we cannot assume 1 access = 1 allocation. :(
233+
let mut rg = evt_rg.addr..evt_rg.end();
234+
while let Some(curr) = rg.next() {
235+
let alloc_id = this
236+
.alloc_id_from_addr(curr.to_u64(), rg.len().try_into().unwrap(), true)
237+
.expect("Foreign code did an out-of-bounds access!");
238+
let alloc = this.get_alloc_raw(alloc_id)?;
239+
let alloc_addr = alloc.get_bytes_unchecked_raw().addr();
240+
241+
// Skip forward however many bytes of the access are contained in the current allocation.
242+
let overlap_size = alloc.len().strict_sub(evt_rg.addr.saturating_sub(alloc_addr));
243+
let _ = rg.advance_by(overlap_size);
244+
245+
// Get an overlap range as an offset from the allocation base addr.
246+
let overlap_start = evt_rg.addr.strict_sub(alloc_addr);
247+
let overlap = overlap_start..overlap_start.strict_add(overlap_size);
248+
249+
// Reads are infallible, writes might not be.
250+
if evt.is_read() {
251+
let p_map = alloc.provenance();
252+
for idx in overlap {
253+
// If a provenance was read by the foreign code, expose it.
254+
if let Some(prov) = p_map.get(Size::from_bytes(idx), this) {
255+
this.expose_provenance(prov)?;
256+
}
248257
}
258+
} else if evt.definitely_happened() || alloc.mutability.is_mut() {
259+
//let (alloc, cx) = this.get_alloc_raw_mut(alloc_id)?;
260+
//alloc.process_native_write(AllocRange { start: overlap.start, size: overlap.len() })
249261
}
250-
} else if evt.definitely_happened() || alloc.mutability.is_mut() {
251-
//let (alloc, cx) = this.get_alloc_raw_mut(alloc_id)?;
252-
//alloc.process_native_write(AllocRange { start: overlap.start, size: overlap.len() })
253262
}
254263
}
255264

0 commit comments

Comments
 (0)