@@ -56,15 +56,14 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
56
56
}
57
57
}
58
58
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 ,
68
67
}
69
68
70
69
/// The value of a function pointer.
@@ -360,8 +359,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
360
359
align,
361
360
CheckInAllocMsg :: MemoryAccessTest ,
362
361
|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) ?;
365
363
Ok ( ( size, align, ( alloc_id, offset, tag) ) )
366
364
} ,
367
365
)
@@ -379,15 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
379
377
msg : CheckInAllocMsg ,
380
378
) -> InterpResult < ' tcx > {
381
379
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) ?;
391
381
Ok ( ( size, align, ( ) ) )
392
382
} ) ?;
393
383
Ok ( ( ) )
@@ -655,30 +645,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
655
645
656
646
/// Obtain the size and alignment of an allocation, even if that allocation has
657
647
/// 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 ) {
665
649
// # Regular allocations
666
650
// Don't use `self.get_raw` here as that will
667
651
// a) cause cycles in case `id` refers to a static
668
652
// b) duplicate a global's allocation in miri
669
653
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 ) ;
671
655
}
672
656
673
657
// # Function pointers
674
658
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
675
659
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 ) ;
682
661
}
683
662
684
663
// # Statics
@@ -690,32 +669,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
690
669
// Use size and align of the type.
691
670
let ty = self . tcx . type_of ( did) ;
692
671
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 )
694
673
}
695
674
Some ( GlobalAlloc :: Memory ( alloc) ) => {
696
675
// Need to duplicate the logic here, because the global allocations have
697
676
// different associated types than the interpreter-local ones.
698
677
let alloc = alloc. inner ( ) ;
699
- Ok ( ( alloc. size ( ) , alloc. align ) )
678
+ ( alloc. size ( ) , alloc. align , AllocKind :: LiveData )
700
679
}
701
680
Some ( GlobalAlloc :: Function ( _) ) => bug ! ( "We already checked function pointers above" ) ,
702
681
// The rest must be dead.
703
682
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 )
715
691
}
716
692
}
717
693
}
718
694
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
+
719
704
fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
720
705
if let Some ( extra) = self . memory . extra_fn_ptr_map . get ( & id) {
721
706
Some ( FnVal :: Other ( * extra) )
@@ -1187,9 +1172,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1187
1172
let ptr = self . scalar_to_ptr ( scalar) ?;
1188
1173
match self . ptr_try_get_alloc_id ( ptr) {
1189
1174
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) ;
1193
1176
// If the pointer is out-of-bounds, it may be null.
1194
1177
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
1195
1178
offset > size
0 commit comments