@@ -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