@@ -227,29 +227,38 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
227
227
228
228
for evt in events. acc_events {
229
229
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!" ) ;
234
230
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
+ }
248
257
}
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() })
249
261
}
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() })
253
262
}
254
263
}
255
264
0 commit comments