@@ -11,7 +11,7 @@ use rand::Rng;
11
11
12
12
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
13
13
use rustc_span:: Span ;
14
- use rustc_target:: abi:: { Align , HasDataLayout , Size } ;
14
+ use rustc_target:: abi:: { Align , Size } ;
15
15
16
16
use crate :: { concurrency:: VClock , * } ;
17
17
@@ -105,15 +105,17 @@ impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
105
105
trait EvalContextExtPriv < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
106
106
// Returns the exposed `AllocId` that corresponds to the specified addr,
107
107
// 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 > {
109
109
let ecx = self . eval_context_ref ( ) ;
110
110
let global_state = ecx. machine . alloc_addresses . borrow ( ) ;
111
111
assert ! ( global_state. provenance_mode != ProvenanceMode :: Strict ) ;
112
112
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 ) } ;
113
116
let pos = global_state. int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) ;
114
117
115
118
// 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.)
117
119
let alloc_id = match pos {
118
120
Ok ( pos) => Some ( global_state. int_to_ptr_map [ pos] . 1 ) ,
119
121
Err ( 0 ) => None ,
@@ -305,20 +307,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
305
307
306
308
let ( prov, offset) = ptr. into_parts ( ) ; // offset is relative (AllocId provenance)
307
309
let alloc_id = prov. alloc_id ( ) ;
308
- let base_addr = ecx. addr_from_alloc_id ( alloc_id, kind) ?;
309
310
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 (
314
314
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) )
317
319
}
318
320
319
321
/// When a pointer is used for a memory access, this computes where in which allocation the
320
322
/// 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 ) > {
322
328
let ecx = self . eval_context_ref ( ) ;
323
329
324
330
let ( tag, addr) = ptr. into_parts ( ) ; // addr is absolute (Tag provenance)
@@ -327,20 +333,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
327
333
alloc_id
328
334
} else {
329
335
// A wildcard pointer.
330
- ecx. alloc_id_from_addr ( addr. bytes ( ) ) ?
336
+ ecx. alloc_id_from_addr ( addr. bytes ( ) , size ) ?
331
337
} ;
332
338
333
339
// This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
334
340
// must have been called in the past, so we can just look up the address in the map.
335
341
let base_addr = * ecx. machine . alloc_addresses . borrow ( ) . base_addr . get ( & alloc_id) . unwrap ( ) ;
336
342
337
343
// 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) ) )
344
346
}
345
347
}
346
348
0 commit comments