@@ -11,7 +11,7 @@ use rand::Rng;
1111
1212use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1313use rustc_span:: Span ;
14- use rustc_target:: abi:: { Align , HasDataLayout , Size } ;
14+ use rustc_target:: abi:: { Align , Size } ;
1515
1616use crate :: { concurrency:: VClock , * } ;
1717
@@ -105,15 +105,17 @@ impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
105105trait EvalContextExtPriv < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
106106 // Returns the exposed `AllocId` that corresponds to the specified addr,
107107 // or `None` if the addr is out of bounds
108- fn alloc_id_from_addr ( & self , addr : u64 ) -> Option < AllocId > {
108+ fn alloc_id_from_addr ( & self , addr : u64 , size : i64 ) -> Option < AllocId > {
109109 let ecx = self . eval_context_ref ( ) ;
110110 let global_state = ecx. machine . alloc_addresses . borrow ( ) ;
111111 assert ! ( global_state. provenance_mode != ProvenanceMode :: Strict ) ;
112112
113+ // We always search the allocation to the right of this address. So if the size is structly
114+ // negative, we have to search for `addr-1` instead.
115+ let addr = if size >= 0 { addr } else { addr. saturating_sub ( 1 ) } ;
113116 let pos = global_state. int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) ;
114117
115118 // Determine the in-bounds provenance for this pointer.
116- // (This is only called on an actual access, so in-bounds is the only possible kind of provenance.)
117119 let alloc_id = match pos {
118120 Ok ( pos) => Some ( global_state. int_to_ptr_map [ pos] . 1 ) ,
119121 Err ( 0 ) => None ,
@@ -305,20 +307,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
305307
306308 let ( prov, offset) = ptr. into_parts ( ) ; // offset is relative (AllocId provenance)
307309 let alloc_id = prov. alloc_id ( ) ;
308- let base_addr = ecx. addr_from_alloc_id ( alloc_id, kind) ?;
309310
310- // Add offset with the right kind of pointer-overflowing arithmetic.
311- let dl = ecx. data_layout ( ) ;
312- let absolute_addr = dl. overflowing_offset ( base_addr, offset. bytes ( ) ) . 0 ;
313- Ok ( interpret:: Pointer :: new (
311+ // Get a pointer to the beginning of this allocation.
312+ let base_addr = ecx. addr_from_alloc_id ( alloc_id, kind) ?;
313+ let base_ptr = interpret:: Pointer :: new (
314314 Provenance :: Concrete { alloc_id, tag } ,
315- Size :: from_bytes ( absolute_addr) ,
316- ) )
315+ Size :: from_bytes ( base_addr) ,
316+ ) ;
317+ // Add offset with the right kind of pointer-overflowing arithmetic.
318+ Ok ( base_ptr. wrapping_offset ( offset, ecx) )
317319 }
318320
319321 /// When a pointer is used for a memory access, this computes where in which allocation the
320322 /// access is going.
321- fn ptr_get_alloc ( & self , ptr : interpret:: Pointer < Provenance > ) -> Option < ( AllocId , Size ) > {
323+ fn ptr_get_alloc (
324+ & self ,
325+ ptr : interpret:: Pointer < Provenance > ,
326+ size : i64 ,
327+ ) -> Option < ( AllocId , Size ) > {
322328 let ecx = self . eval_context_ref ( ) ;
323329
324330 let ( tag, addr) = ptr. into_parts ( ) ; // addr is absolute (Tag provenance)
@@ -327,20 +333,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
327333 alloc_id
328334 } else {
329335 // A wildcard pointer.
330- ecx. alloc_id_from_addr ( addr. bytes ( ) ) ?
336+ ecx. alloc_id_from_addr ( addr. bytes ( ) , size ) ?
331337 } ;
332338
333339 // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
334340 // must have been called in the past, so we can just look up the address in the map.
335341 let base_addr = * ecx. machine . alloc_addresses . borrow ( ) . base_addr . get ( & alloc_id) . unwrap ( ) ;
336342
337343 // Wrapping "addr - base_addr"
338- #[ allow( clippy:: cast_possible_wrap) ] // we want to wrap here
339- let neg_base_addr = ( base_addr as i64 ) . wrapping_neg ( ) ;
340- Some ( (
341- alloc_id,
342- Size :: from_bytes ( ecx. overflowing_signed_offset ( addr. bytes ( ) , neg_base_addr) . 0 ) ,
343- ) )
344+ let rel_offset = ecx. truncate_to_target_usize ( addr. bytes ( ) . wrapping_sub ( base_addr) ) ;
345+ Some ( ( alloc_id, Size :: from_bytes ( rel_offset) ) )
344346 }
345347}
346348
0 commit comments