@@ -262,7 +262,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
262262 Scalar :: Ptr ( ptr) => {
263263 // check this is not NULL -- which we can ensure only if this is in-bounds
264264 // of some (potentially dead) allocation.
265- let align = self . check_bounds_ptr_maybe_dead ( ptr) ?;
265+ let align = self . check_bounds_ptr ( ptr, InboundsCheck :: MaybeDead ) ?;
266266 ( ptr. offset . bytes ( ) , align)
267267 }
268268 Scalar :: Bits { bits, size } => {
@@ -297,17 +297,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
297297 /// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
298298 /// of an allocation (i.e., at the first *inaccessible* location) *is* considered
299299 /// in-bounds! This follows C's/LLVM's rules.
300- /// This function also works for deallocated allocations.
301- /// Use `.get(ptr.alloc_id)?.check_bounds_ptr(ptr)` if you want to force the allocation
302- /// to still be live.
303300 /// If you want to check bounds before doing a memory access, better first obtain
304301 /// an `Allocation` and call `check_bounds`.
305- pub fn check_bounds_ptr_maybe_dead (
302+ pub fn check_bounds_ptr (
306303 & self ,
307304 ptr : Pointer < M :: PointerTag > ,
305+ liveness : InboundsCheck ,
308306 ) -> EvalResult < ' tcx , Align > {
309- let ( allocation_size, align) = self . get_size_and_align ( ptr. alloc_id ) ;
310- ptr. check_in_alloc ( allocation_size, InboundsCheck :: MaybeDead ) ?;
307+ let ( allocation_size, align) = self . get_size_and_align ( ptr. alloc_id , liveness ) ? ;
308+ ptr. check_in_alloc ( allocation_size, liveness ) ?;
311309 Ok ( align)
312310 }
313311}
@@ -429,27 +427,37 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
429427 }
430428 }
431429
432- pub fn get_size_and_align ( & self , id : AllocId ) -> ( Size , Align ) {
430+ /// Obtain the size and alignment of an allocation, even if that allocation has been deallocated
431+ ///
432+ /// If `liveness` is `InboundsCheck::Dead`, this function always returns `Ok`
433+ pub fn get_size_and_align (
434+ & self ,
435+ id : AllocId ,
436+ liveness : InboundsCheck ,
437+ ) -> EvalResult < ' static , ( Size , Align ) > {
433438 if let Ok ( alloc) = self . get ( id) {
434- return ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ;
439+ return Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ;
435440 }
436441 // Could also be a fn ptr or extern static
437442 match self . tcx . alloc_map . lock ( ) . get ( id) {
438- Some ( AllocKind :: Function ( ..) ) => ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) ,
443+ Some ( AllocKind :: Function ( ..) ) => Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) ) ,
439444 Some ( AllocKind :: Static ( did) ) => {
440445 // The only way `get` couldn't have worked here is if this is an extern static
441446 assert ! ( self . tcx. is_foreign_item( did) ) ;
442447 // Use size and align of the type
443448 let ty = self . tcx . type_of ( did) ;
444449 let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
445- ( layout. size , layout. align . abi )
446- }
447- _ => {
448- // Must be a deallocated pointer
449- * self . dead_alloc_map . get ( & id) . expect (
450- "allocation missing in dead_alloc_map"
451- )
450+ Ok ( ( layout. size , layout. align . abi ) )
452451 }
452+ _ => match liveness {
453+ InboundsCheck :: MaybeDead => {
454+ // Must be a deallocated pointer
455+ Ok ( * self . dead_alloc_map . get ( & id) . expect (
456+ "allocation missing in dead_alloc_map"
457+ ) )
458+ } ,
459+ InboundsCheck :: Live => err ! ( DanglingPointerDeref ) ,
460+ } ,
453461 }
454462 }
455463
0 commit comments