@@ -107,47 +107,6 @@ fn align_addr(addr: u64, align: u64) -> u64 {
107
107
108
108
impl < ' tcx > EvalContextExtPriv < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
109
109
trait 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
-
151
110
fn addr_from_alloc_id_uncached (
152
111
& self ,
153
112
global_state : & mut GlobalStateInner ,
@@ -242,11 +201,65 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
242
201
interp_ok ( base_addr)
243
202
}
244
203
}
204
+ }
245
205
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`.
246
259
fn addr_from_alloc_id (
247
260
& self ,
248
261
alloc_id : AllocId ,
249
- memory_kind : MemoryKind ,
262
+ memory_kind : Option < MemoryKind > ,
250
263
) -> InterpResult < ' tcx , u64 > {
251
264
let this = self . eval_context_ref ( ) ;
252
265
let mut global_state = this. machine . alloc_addresses . borrow_mut ( ) ;
@@ -256,8 +269,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
256
269
Some ( & addr) => interp_ok ( addr) ,
257
270
None => {
258
271
// 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" ) ;
259
274
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) ?;
261
276
trace ! ( "Assigning base address {:#x} to allocation {:?}" , base_addr, alloc_id) ;
262
277
263
278
// Store address in cache.
@@ -283,10 +298,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
283
298
}
284
299
}
285
300
}
286
- }
287
301
288
- impl < ' tcx > EvalContextExt < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
289
- pub trait EvalContextExt < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
290
302
fn expose_provenance ( & self , provenance : Provenance ) -> InterpResult < ' tcx > {
291
303
let this = self . eval_context_ref ( ) ;
292
304
let mut global_state = this. machine . alloc_addresses . borrow_mut ( ) ;
@@ -365,7 +377,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
365
377
let alloc_id = prov. alloc_id ( ) ;
366
378
367
379
// 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) ) ?;
369
381
let base_ptr = interpret:: Pointer :: new (
370
382
Provenance :: Concrete { alloc_id, tag } ,
371
383
Size :: from_bytes ( base_addr) ,
@@ -388,7 +400,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
388
400
// In native lib mode, MiriAllocBytes for global allocations are handled via `prepared_alloc_bytes`.
389
401
// This additional call ensures that some `MiriAllocBytes` are always prepared, just in case
390
402
// 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 ( ) ) ) ?;
392
404
// The memory we need here will have already been allocated during an earlier call to
393
405
// `addr_from_alloc_id` for this allocation. So don't create a new `MiriAllocBytes` here, instead
394
406
// fetch the previously prepared bytes from `prepared_alloc_bytes`.
@@ -423,7 +435,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
423
435
alloc_id
424
436
} else {
425
437
// 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) ?
427
440
} ;
428
441
429
442
// This cannot fail: since we already have a pointer with that provenance, adjust_alloc_root_pointer
0 commit comments