@@ -492,13 +492,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
492492 id : AllocId ,
493493 liveness : AllocCheck ,
494494 ) -> InterpResult < ' static , ( Size , Align ) > {
495- if let Ok ( alloc) = self . get ( id) {
495+ // # Regular allocations
496+ // Don't use `self.get` here as that will
497+ // a) cause cycles in case `id` refers to a static
498+ // b) duplicate a static's allocation in miri
499+ if let Some ( ( _, alloc) ) = self . alloc_map . get ( id) {
496500 return Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ;
497501 }
498- // can't do this in the match argument, we may get cycle errors since the lock would get
499- // dropped after the match.
502+
503+ // # Statics and function pointers
504+ // Can't do this in the match argument, we may get cycle errors since the lock would
505+ // be held throughout the match.
500506 let alloc = self . tcx . alloc_map . lock ( ) . get ( id) ;
501- // Could also be a fn ptr or extern static
502507 match alloc {
503508 Some ( GlobalAlloc :: Function ( ..) ) => {
504509 if let AllocCheck :: Dereferencable = liveness {
@@ -507,28 +512,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
507512 } else {
508513 Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
509514 }
510- }
511- // `self.get` would also work, but can cause cycles if a static refers to itself
515+ } ,
512516 Some ( GlobalAlloc :: Static ( did) ) => {
513- // The only way `get` couldn't have worked here is if this is an extern static
514- assert ! ( self . tcx. is_foreign_item( did) ) ;
515- // Use size and align of the type
517+ // Use size and align of the type.
516518 let ty = self . tcx . type_of ( did) ;
517519 let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
518520 Ok ( ( layout. size , layout. align . abi ) )
519- }
520- _ => {
521- if let Ok ( alloc) = self . get ( id) {
522- Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) )
523- }
524- else if let AllocCheck :: MaybeDead = liveness {
525- // Deallocated pointers are allowed, we should be able to find
526- // them in the map.
527- Ok ( * self . dead_alloc_map . get ( & id)
528- . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
529- } else {
530- err ! ( DanglingPointerDeref )
531- }
521+ } ,
522+ Some ( GlobalAlloc :: Memory ( alloc) ) =>
523+ // Need to duplicate the logic here, because the global allocations have
524+ // different associated types than the interpreter-local ones.
525+ Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ,
526+ // The rest must be dead.
527+ None => if let AllocCheck :: MaybeDead = liveness {
528+ // Deallocated pointers are allowed, we should be able to find
529+ // them in the map.
530+ Ok ( * self . dead_alloc_map . get ( & id)
531+ . expect ( "deallocated pointers should all be recorded in \
532+ `dead_alloc_map`") )
533+ } else {
534+ err ! ( DanglingPointerDeref )
532535 } ,
533536 }
534537 }
0 commit comments