@@ -107,47 +107,6 @@ fn align_addr(addr: u64, align: u64) -> u64 {
107107
108108impl < ' tcx > EvalContextExtPriv < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
109109trait EvalContextExtPriv < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
110- // Returns the exposed `AllocId` that corresponds to the specified addr,
111- // or `None` if the addr is out of bounds
112- fn alloc_id_from_addr ( & self , addr : u64 , size : i64 ) -> Option < AllocId > {
113- let this = self . eval_context_ref ( ) ;
114- let global_state = this. machine . alloc_addresses . borrow ( ) ;
115- assert ! ( global_state. provenance_mode != ProvenanceMode :: Strict ) ;
116-
117- // We always search the allocation to the right of this address. So if the size is structly
118- // negative, we have to search for `addr-1` instead.
119- let addr = if size >= 0 { addr } else { addr. saturating_sub ( 1 ) } ;
120- let pos = global_state. int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) ;
121-
122- // Determine the in-bounds provenance for this pointer.
123- let alloc_id = match pos {
124- Ok ( pos) => Some ( global_state. int_to_ptr_map [ pos] . 1 ) ,
125- Err ( 0 ) => None ,
126- Err ( pos) => {
127- // This is the largest of the addresses smaller than `int`,
128- // i.e. the greatest lower bound (glb)
129- let ( glb, alloc_id) = global_state. int_to_ptr_map [ pos - 1 ] ;
130- // This never overflows because `addr >= glb`
131- let offset = addr - glb;
132- // We require this to be strict in-bounds of the allocation. This arm is only
133- // entered for addresses that are not the base address, so even zero-sized
134- // allocations will get recognized at their base address -- but all other
135- // allocations will *not* be recognized at their "end" address.
136- let size = this. get_alloc_info ( alloc_id) . size ;
137- if offset < size. bytes ( ) { Some ( alloc_id) } else { None }
138- }
139- } ?;
140-
141- // We only use this provenance if it has been exposed.
142- if global_state. exposed . contains ( & alloc_id) {
143- // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
144- debug_assert ! ( this. is_alloc_live( alloc_id) ) ;
145- Some ( alloc_id)
146- } else {
147- None
148- }
149- }
150-
151110 fn addr_from_alloc_id_uncached (
152111 & self ,
153112 global_state : & mut GlobalStateInner ,
@@ -242,11 +201,65 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
242201 interp_ok ( base_addr)
243202 }
244203 }
204+ }
245205
206+ impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
207+ pub trait EvalContextExt < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
208+ // Returns the `AllocId` that corresponds to the specified addr,
209+ // or `None` if the addr is out of bounds.
210+ // Setting `only_exposed_allocations` selects whether only exposed allocations are considered.
211+ fn alloc_id_from_addr (
212+ & self ,
213+ addr : u64 ,
214+ size : i64 ,
215+ only_exposed_allocations : bool ,
216+ ) -> Option < AllocId > {
217+ let this = self . eval_context_ref ( ) ;
218+ let global_state = this. machine . alloc_addresses . borrow ( ) ;
219+ assert ! ( global_state. provenance_mode != ProvenanceMode :: Strict ) ;
220+
221+ // We always search the allocation to the right of this address. So if the size is strictly
222+ // negative, we have to search for `addr-1` instead.
223+ let addr = if size >= 0 { addr } else { addr. saturating_sub ( 1 ) } ;
224+ let pos = global_state. int_to_ptr_map . binary_search_by_key ( & addr, |( addr, _) | * addr) ;
225+
226+ // Determine the in-bounds provenance for this pointer.
227+ let alloc_id = match pos {
228+ Ok ( pos) => Some ( global_state. int_to_ptr_map [ pos] . 1 ) ,
229+ Err ( 0 ) => None ,
230+ Err ( pos) => {
231+ // This is the largest of the addresses smaller than `int`,
232+ // i.e. the greatest lower bound (glb)
233+ let ( glb, alloc_id) = global_state. int_to_ptr_map [ pos - 1 ] ;
234+ // This never overflows because `addr >= glb`
235+ let offset = addr - glb;
236+ // We require this to be strict in-bounds of the allocation. This arm is only
237+ // entered for addresses that are not the base address, so even zero-sized
238+ // allocations will get recognized at their base address -- but all other
239+ // allocations will *not* be recognized at their "end" address.
240+ let size = this. get_alloc_info ( alloc_id) . size ;
241+ if offset < size. bytes ( ) { Some ( alloc_id) } else { None }
242+ }
243+ } ?;
244+
245+ // We only use this provenance if it has been exposed, or if the caller requested also non-exposed allocations
246+ if !only_exposed_allocations || global_state. exposed . contains ( & alloc_id) {
247+ // This must still be live, since we remove allocations from `int_to_ptr_map` when they get freed.
248+ debug_assert ! ( this. is_alloc_live( alloc_id) ) ;
249+ Some ( alloc_id)
250+ } else {
251+ None
252+ }
253+ }
254+
255+ /// Returns the base address of an allocation, or an error if no base address could be found
256+ ///
257+ /// # Panics
258+ /// If `memory_kind = None` and the `alloc_id` is not cached, meaning that the first call to this function per `alloc_id` must get the `memory_kind`.
246259 fn addr_from_alloc_id (
247260 & self ,
248261 alloc_id : AllocId ,
249- memory_kind : MemoryKind ,
262+ memory_kind : Option < MemoryKind > ,
250263 ) -> InterpResult < ' tcx , u64 > {
251264 let this = self . eval_context_ref ( ) ;
252265 let mut global_state = this. machine . alloc_addresses . borrow_mut ( ) ;
@@ -256,8 +269,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
256269 Some ( & addr) => interp_ok ( addr) ,
257270 None => {
258271 // First time we're looking for the absolute address of this allocation.
272+ let memory_kind =
273+ memory_kind. expect ( "memory_kind is required since alloc_id is not cached" ) ;
259274 let base_addr =
260- self . addr_from_alloc_id_uncached ( global_state, alloc_id, memory_kind) ?;
275+ this . addr_from_alloc_id_uncached ( global_state, alloc_id, memory_kind) ?;
261276 trace ! ( "Assigning base address {:#x} to allocation {:?}" , base_addr, alloc_id) ;
262277
263278 // Store address in cache.
@@ -283,10 +298,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
283298 }
284299 }
285300 }
286- }
287301
288- impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
289- pub trait EvalContextExt < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
290302 fn expose_provenance ( & self , provenance : Provenance ) -> InterpResult < ' tcx > {
291303 let this = self . eval_context_ref ( ) ;
292304 let mut global_state = this. machine . alloc_addresses . borrow_mut ( ) ;
@@ -365,7 +377,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
365377 let alloc_id = prov. alloc_id ( ) ;
366378
367379 // Get a pointer to the beginning of this allocation.
368- let base_addr = this. addr_from_alloc_id ( alloc_id, kind) ?;
380+ let base_addr = this. addr_from_alloc_id ( alloc_id, Some ( kind) ) ?;
369381 let base_ptr = interpret:: Pointer :: new (
370382 Provenance :: Concrete { alloc_id, tag } ,
371383 Size :: from_bytes ( base_addr) ,
@@ -388,7 +400,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
388400 // In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
389401 // This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
390402 // this function gets called before the first time `addr_from_alloc_id` gets called.
391- this. addr_from_alloc_id ( id, MiriMemoryKind :: Global . into ( ) ) ?;
403+ this. addr_from_alloc_id ( id, Some ( MiriMemoryKind :: Global . into ( ) ) ) ?;
392404 // The memory we need here will have already been allocated during an earlier call to
393405 // `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
394406 // fetch the previously prepared bytes from `prepared_alloc_bytes`.
@@ -423,7 +435,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
423435 alloc_id
424436 } else {
425437 // A wildcard pointer.
426- this. alloc_id_from_addr ( addr. bytes ( ) , size) ?
438+ let only_exposed_allocations = true ;
439+ this. alloc_id_from_addr ( addr. bytes ( ) , size, only_exposed_allocations) ?
427440 } ;
428441
429442 // This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
0 commit comments