@@ -162,11 +162,14 @@ impl<'mir, 'tcx> GlobalStateInner {
162162 Ok ( Pointer :: new ( Some ( Provenance :: Wildcard ) , Size :: from_bytes ( addr) ) )
163163 }
164164
165- fn alloc_base_addr ( ecx : & MiriInterpCx < ' mir , ' tcx > , alloc_id : AllocId ) -> u64 {
165+ fn alloc_base_addr (
166+ ecx : & MiriInterpCx < ' mir , ' tcx > ,
167+ alloc_id : AllocId ,
168+ ) -> InterpResult < ' tcx , u64 > {
166169 let mut global_state = ecx. machine . intptrcast . borrow_mut ( ) ;
167170 let global_state = & mut * global_state;
168171
169- match global_state. base_addr . entry ( alloc_id) {
172+ Ok ( match global_state. base_addr . entry ( alloc_id) {
170173 Entry :: Occupied ( entry) => * entry. get ( ) ,
171174 Entry :: Vacant ( entry) => {
172175 // There is nothing wrong with a raw pointer being cast to an integer only after
@@ -181,7 +184,10 @@ impl<'mir, 'tcx> GlobalStateInner {
181184 rng. gen_range ( 0 ..16 )
182185 } ;
183186 // From next_base_addr + slack, round up to adjust for alignment.
184- let base_addr = global_state. next_base_addr . checked_add ( slack) . unwrap ( ) ;
187+ let base_addr = global_state
188+ . next_base_addr
189+ . checked_add ( slack)
190+ . ok_or_else ( || err_exhaust ! ( AddressSpaceFull ) ) ?;
185191 let base_addr = Self :: align_addr ( base_addr, align. bytes ( ) ) ;
186192 entry. insert ( base_addr) ;
187193 trace ! (
@@ -197,24 +203,33 @@ impl<'mir, 'tcx> GlobalStateInner {
197203 // of at least 1 to avoid two allocations having the same base address.
198204 // (The logic in `alloc_id_from_addr` assumes unique addresses, and different
199205 // function/vtable pointers need to be distinguishable!)
200- global_state. next_base_addr = base_addr. checked_add ( max ( size. bytes ( ) , 1 ) ) . unwrap ( ) ;
206+ global_state. next_base_addr = base_addr
207+ . checked_add ( max ( size. bytes ( ) , 1 ) )
208+ . ok_or_else ( || err_exhaust ! ( AddressSpaceFull ) ) ?;
209+ // Even if `Size` didn't overflow, we might still have filled up the address space.
210+ if global_state. next_base_addr > ecx. machine_usize_max ( ) {
211+ throw_exhaust ! ( AddressSpaceFull ) ;
212+ }
201213 // Given that `next_base_addr` increases in each allocation, pushing the
202214 // corresponding tuple keeps `int_to_ptr_map` sorted
203215 global_state. int_to_ptr_map . push ( ( base_addr, alloc_id) ) ;
204216
205217 base_addr
206218 }
207- }
219+ } )
208220 }
209221
210222 /// Convert a relative (tcx) pointer to an absolute address.
211- pub fn rel_ptr_to_addr ( ecx : & MiriInterpCx < ' mir , ' tcx > , ptr : Pointer < AllocId > ) -> u64 {
223+ pub fn rel_ptr_to_addr (
224+ ecx : & MiriInterpCx < ' mir , ' tcx > ,
225+ ptr : Pointer < AllocId > ,
226+ ) -> InterpResult < ' tcx , u64 > {
212227 let ( alloc_id, offset) = ptr. into_parts ( ) ; // offset is relative (AllocId provenance)
213- let base_addr = GlobalStateInner :: alloc_base_addr ( ecx, alloc_id) ;
228+ let base_addr = GlobalStateInner :: alloc_base_addr ( ecx, alloc_id) ? ;
214229
215230 // Add offset with the right kind of pointer-overflowing arithmetic.
216231 let dl = ecx. data_layout ( ) ;
217- dl. overflowing_offset ( base_addr, offset. bytes ( ) ) . 0
232+ Ok ( dl. overflowing_offset ( base_addr, offset. bytes ( ) ) . 0 )
218233 }
219234
220235 /// When a pointer is used for a memory access, this computes where in which allocation the
@@ -232,7 +247,9 @@ impl<'mir, 'tcx> GlobalStateInner {
232247 GlobalStateInner :: alloc_id_from_addr ( ecx, addr. bytes ( ) ) ?
233248 } ;
234249
235- let base_addr = GlobalStateInner :: alloc_base_addr ( ecx, alloc_id) ;
250+ // This cannot fail: since we already have a pointer with that provenance, rel_ptr_to_addr
251+ // must have been called in the past.
252+ let base_addr = GlobalStateInner :: alloc_base_addr ( ecx, alloc_id) . unwrap ( ) ;
236253
237254 // Wrapping "addr - base_addr"
238255 let dl = ecx. data_layout ( ) ;
0 commit comments