@@ -56,15 +56,14 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
5656 }
5757}
5858
59- /// Used by `get_size_and_align` to indicate whether the allocation needs to be live.
60- #[ derive( Debug , Copy , Clone ) ]
61- pub enum AllocCheck {
62- /// Allocation must be live and not a function pointer.
63- Dereferenceable ,
64- /// Allocations needs to be live, but may be a function pointer.
65- Live ,
66- /// Allocation may be dead.
67- MaybeDead ,
59+ /// The return value of `get_alloc_info` indicates the "kind" of the allocation.
60+ pub enum AllocKind {
61+ /// A regular live data allocation.
62+ LiveData ,
63+ /// A function allocation (that fn ptrs point to).
64+ Function ,
65+ /// A dead allocation.
66+ Dead ,
6867}
6968
7069/// The value of a function pointer.
@@ -360,8 +359,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
360359 align,
361360 CheckInAllocMsg :: MemoryAccessTest ,
362361 |alloc_id, offset, tag| {
363- let ( size, align) =
364- self . get_alloc_size_and_align ( alloc_id, AllocCheck :: Dereferenceable ) ?;
362+ let ( size, align) = self . get_live_alloc_size_and_align ( alloc_id) ?;
365363 Ok ( ( size, align, ( alloc_id, offset, tag) ) )
366364 } ,
367365 )
@@ -379,15 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
379377 msg : CheckInAllocMsg ,
380378 ) -> InterpResult < ' tcx > {
381379 self . check_and_deref_ptr ( ptr, size, Some ( align) , msg, |alloc_id, _, _| {
382- let check = match msg {
383- CheckInAllocMsg :: DerefTest | CheckInAllocMsg :: MemoryAccessTest => {
384- AllocCheck :: Dereferenceable
385- }
386- CheckInAllocMsg :: PointerArithmeticTest
387- | CheckInAllocMsg :: OffsetFromTest
388- | CheckInAllocMsg :: InboundsTest => AllocCheck :: Live ,
389- } ;
390- let ( size, align) = self . get_alloc_size_and_align ( alloc_id, check) ?;
380+ let ( size, align) = self . get_live_alloc_size_and_align ( alloc_id) ?;
391381 Ok ( ( size, align, ( ) ) )
392382 } ) ?;
393383 Ok ( ( ) )
@@ -655,30 +645,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
655645
656646 /// Obtain the size and alignment of an allocation, even if that allocation has
657647 /// been deallocated.
658- ///
659- /// If `liveness` is `AllocCheck::MaybeDead`, this function always returns `Ok`.
660- pub fn get_alloc_size_and_align (
661- & self ,
662- id : AllocId ,
663- liveness : AllocCheck ,
664- ) -> InterpResult < ' tcx , ( Size , Align ) > {
648+ pub fn get_alloc_info ( & self , id : AllocId ) -> ( Size , Align , AllocKind ) {
665649 // # Regular allocations
666650 // Don't use `self.get_raw` here as that will
667651 // a) cause cycles in case `id` refers to a static
668652 // b) duplicate a global's allocation in miri
669653 if let Some ( ( _, alloc) ) = self . memory . alloc_map . get ( id) {
670- return Ok ( ( alloc. size ( ) , alloc. align ) ) ;
654+ return ( alloc. size ( ) , alloc. align , AllocKind :: LiveData ) ;
671655 }
672656
673657 // # Function pointers
674658 // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
675659 if self . get_fn_alloc ( id) . is_some ( ) {
676- return if let AllocCheck :: Dereferenceable = liveness {
677- // The caller requested no function pointers.
678- throw_ub ! ( DerefFunctionPointer ( id) )
679- } else {
680- Ok ( ( Size :: ZERO , Align :: ONE ) )
681- } ;
660+ return ( Size :: ZERO , Align :: ONE , AllocKind :: Function ) ;
682661 }
683662
684663 // # Statics
@@ -690,32 +669,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
690669 // Use size and align of the type.
691670 let ty = self . tcx . type_of ( did) ;
692671 let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
693- Ok ( ( layout. size , layout. align . abi ) )
672+ ( layout. size , layout. align . abi , AllocKind :: LiveData )
694673 }
695674 Some ( GlobalAlloc :: Memory ( alloc) ) => {
696675 // Need to duplicate the logic here, because the global allocations have
697676 // different associated types than the interpreter-local ones.
698677 let alloc = alloc. inner ( ) ;
699- Ok ( ( alloc. size ( ) , alloc. align ) )
678+ ( alloc. size ( ) , alloc. align , AllocKind :: LiveData )
700679 }
701680 Some ( GlobalAlloc :: Function ( _) ) => bug ! ( "We already checked function pointers above" ) ,
702681 // The rest must be dead.
703682 None => {
704- if let AllocCheck :: MaybeDead = liveness {
705- // Deallocated pointers are allowed, we should be able to find
706- // them in the map.
707- Ok ( * self
708- . memory
709- . dead_alloc_map
710- . get ( & id)
711- . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
712- } else {
713- throw_ub ! ( PointerUseAfterFree ( id) )
714- }
683+ // Deallocated pointers are allowed, we should be able to find
684+ // them in the map.
685+ let ( size, align) = * self
686+ . memory
687+ . dead_alloc_map
688+ . get ( & id)
689+ . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) ;
690+ ( size, align, AllocKind :: Dead )
715691 }
716692 }
717693 }
718694
695+ /// Obtain the size and alignment of a live allocation.
696+ pub fn get_live_alloc_size_and_align ( & self , id : AllocId ) -> InterpResult < ' tcx , ( Size , Align ) > {
697+ let ( size, align, kind) = self . get_alloc_info ( id) ;
698+ if matches ! ( kind, AllocKind :: Dead ) {
699+ throw_ub ! ( PointerUseAfterFree ( id) )
700+ }
701+ Ok ( ( size, align) )
702+ }
703+
719704 fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
720705 if let Some ( extra) = self . memory . extra_fn_ptr_map . get ( & id) {
721706 Some ( FnVal :: Other ( * extra) )
@@ -1187,9 +1172,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
11871172 let ptr = self . scalar_to_ptr ( scalar) ?;
11881173 match self . ptr_try_get_alloc_id ( ptr) {
11891174 Ok ( ( alloc_id, offset, _) ) => {
1190- let ( size, _align) = self
1191- . get_alloc_size_and_align ( alloc_id, AllocCheck :: MaybeDead )
1192- . expect ( "alloc info with MaybeDead cannot fail" ) ;
1175+ let ( size, _align, _kind) = self . get_alloc_info ( alloc_id) ;
11931176 // If the pointer is out-of-bounds, it may be null.
11941177 // Note that one-past-the-end (offset == size) is still inbounds, and never null.
11951178 offset > size
0 commit comments