@@ -14,10 +14,9 @@ use std::{fmt, mem, ptr};
14
14
use rustc_abi:: { Align , HasDataLayout , Size } ;
15
15
use rustc_ast:: Mutability ;
16
16
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap } ;
17
- use rustc_hir:: def:: DefKind ;
18
17
use rustc_middle:: bug;
19
18
use rustc_middle:: mir:: display_allocation;
20
- use rustc_middle:: ty:: { self , Instance , ParamEnv , Ty , TyCtxt } ;
19
+ use rustc_middle:: ty:: { self , Instance , Ty , TyCtxt } ;
21
20
use tracing:: { debug, instrument, trace} ;
22
21
23
22
use super :: {
@@ -72,6 +71,21 @@ pub enum AllocKind {
72
71
Dead ,
73
72
}
74
73
74
+ /// Metadata about an `AllocId`.
75
+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
76
+ pub struct AllocInfo {
77
+ pub size : Size ,
78
+ pub align : Align ,
79
+ pub kind : AllocKind ,
80
+ pub mutbl : Mutability ,
81
+ }
82
+
83
+ impl AllocInfo {
84
+ fn new ( size : Size , align : Align , kind : AllocKind , mutbl : Mutability ) -> Self {
85
+ Self { size, align, kind, mutbl }
86
+ }
87
+ }
88
+
75
89
/// The value of a function pointer.
76
90
#[ derive( Debug , Copy , Clone ) ]
77
91
pub enum FnVal < ' tcx , Other > {
@@ -524,17 +538,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
524
538
match self . ptr_try_get_alloc_id ( ptr, 0 ) {
525
539
Err ( addr) => is_offset_misaligned ( addr, align) ,
526
540
Ok ( ( alloc_id, offset, _prov) ) => {
527
- let ( _size, alloc_align, kind) = self . get_alloc_info ( alloc_id) ;
528
- if let Some ( misalign) =
529
- M :: alignment_check ( self , alloc_id, alloc_align, kind, offset, align)
530
- {
541
+ let alloc_info = self . get_alloc_info ( alloc_id) ;
542
+ if let Some ( misalign) = M :: alignment_check (
543
+ self ,
544
+ alloc_id,
545
+ alloc_info. align ,
546
+ alloc_info. kind ,
547
+ offset,
548
+ align,
549
+ ) {
531
550
Some ( misalign)
532
551
} else if M :: Provenance :: OFFSET_IS_ADDR {
533
552
is_offset_misaligned ( ptr. addr ( ) . bytes ( ) , align)
534
553
} else {
535
554
// Check allocation alignment and offset alignment.
536
- if alloc_align . bytes ( ) < align. bytes ( ) {
537
- Some ( Misalignment { has : alloc_align , required : align } )
555
+ if alloc_info . align . bytes ( ) < align. bytes ( ) {
556
+ Some ( Misalignment { has : alloc_info . align , required : align } )
538
557
} else {
539
558
is_offset_misaligned ( offset. bytes ( ) , align)
540
559
}
@@ -818,82 +837,45 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
818
837
819
838
/// Obtain the size and alignment of an allocation, even if that allocation has
820
839
/// been deallocated.
821
- pub fn get_alloc_info ( & self , id : AllocId ) -> ( Size , Align , AllocKind ) {
840
+ pub fn get_alloc_info ( & self , id : AllocId ) -> AllocInfo {
822
841
// # Regular allocations
823
842
// Don't use `self.get_raw` here as that will
824
843
// a) cause cycles in case `id` refers to a static
825
844
// b) duplicate a global's allocation in miri
826
845
if let Some ( ( _, alloc) ) = self . memory . alloc_map . get ( id) {
827
- return ( alloc. size ( ) , alloc. align , AllocKind :: LiveData ) ;
846
+ return AllocInfo :: new (
847
+ alloc. size ( ) ,
848
+ alloc. align ,
849
+ AllocKind :: LiveData ,
850
+ alloc. mutability ,
851
+ ) ;
828
852
}
829
853
830
854
// # Function pointers
831
855
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
832
856
if self . get_fn_alloc ( id) . is_some ( ) {
833
- return ( Size :: ZERO , Align :: ONE , AllocKind :: Function ) ;
857
+ return AllocInfo :: new ( Size :: ZERO , Align :: ONE , AllocKind :: Function , Mutability :: Not ) ;
834
858
}
835
859
836
- // # Statics
837
- // Can't do this in the match argument, we may get cycle errors since the lock would
838
- // be held throughout the match.
839
- match self . tcx . try_get_global_alloc ( id) {
840
- Some ( GlobalAlloc :: Static ( def_id) ) => {
841
- // Thread-local statics do not have a constant address. They *must* be accessed via
842
- // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
843
- assert ! ( !self . tcx. is_thread_local_static( def_id) ) ;
844
-
845
- let DefKind :: Static { nested, .. } = self . tcx . def_kind ( def_id) else {
846
- bug ! ( "GlobalAlloc::Static is not a static" )
847
- } ;
848
-
849
- let ( size, align) = if nested {
850
- // Nested anonymous statics are untyped, so let's get their
851
- // size and alignment from the allocation itself. This always
852
- // succeeds, as the query is fed at DefId creation time, so no
853
- // evaluation actually occurs.
854
- let alloc = self . tcx . eval_static_initializer ( def_id) . unwrap ( ) ;
855
- ( alloc. 0 . size ( ) , alloc. 0 . align )
856
- } else {
857
- // Use size and align of the type for everything else. We need
858
- // to do that to
859
- // * avoid cycle errors in case of self-referential statics,
860
- // * be able to get information on extern statics.
861
- let ty = self
862
- . tcx
863
- . type_of ( def_id)
864
- . no_bound_vars ( )
865
- . expect ( "statics should not have generic parameters" ) ;
866
- let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
867
- assert ! ( layout. is_sized( ) ) ;
868
- ( layout. size , layout. align . abi )
869
- } ;
870
- ( size, align, AllocKind :: LiveData )
871
- }
872
- Some ( GlobalAlloc :: Memory ( alloc) ) => {
873
- // Need to duplicate the logic here, because the global allocations have
874
- // different associated types than the interpreter-local ones.
875
- let alloc = alloc. inner ( ) ;
876
- ( alloc. size ( ) , alloc. align , AllocKind :: LiveData )
877
- }
878
- Some ( GlobalAlloc :: Function { .. } ) => {
879
- bug ! ( "We already checked function pointers above" )
880
- }
881
- Some ( GlobalAlloc :: VTable ( ..) ) => {
882
- // No data to be accessed here. But vtables are pointer-aligned.
883
- return ( Size :: ZERO , self . tcx . data_layout . pointer_align . abi , AllocKind :: VTable ) ;
884
- }
885
- // The rest must be dead.
886
- None => {
887
- // Deallocated pointers are allowed, we should be able to find
888
- // them in the map.
889
- let ( size, align) = * self
890
- . memory
891
- . dead_alloc_map
892
- . get ( & id)
893
- . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) ;
894
- ( size, align, AllocKind :: Dead )
895
- }
860
+ // # Global allocations
861
+ if let Some ( global_alloc) = self . tcx . try_get_global_alloc ( id) {
862
+ let ( size, align) = global_alloc. size_and_align ( * self . tcx , self . param_env ) ;
863
+ let mutbl = global_alloc. mutability ( * self . tcx , self . param_env ) ;
864
+ let kind = match global_alloc {
865
+ GlobalAlloc :: Static { .. } | GlobalAlloc :: Memory { .. } => AllocKind :: LiveData ,
866
+ GlobalAlloc :: Function { .. } => bug ! ( "We already checked function pointers above" ) ,
867
+ GlobalAlloc :: VTable { .. } => AllocKind :: VTable ,
868
+ } ;
869
+ return AllocInfo :: new ( size, align, kind, mutbl) ;
896
870
}
871
+
872
+ // # Dead pointers
873
+ let ( size, align) = * self
874
+ . memory
875
+ . dead_alloc_map
876
+ . get ( & id)
877
+ . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) ;
878
+ AllocInfo :: new ( size, align, AllocKind :: Dead , Mutability :: Not )
897
879
}
898
880
899
881
/// Obtain the size and alignment of a *live* allocation.
@@ -902,11 +884,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
902
884
id : AllocId ,
903
885
msg : CheckInAllocMsg ,
904
886
) -> InterpResult < ' tcx , ( Size , Align ) > {
905
- let ( size , align , kind ) = self . get_alloc_info ( id) ;
906
- if matches ! ( kind, AllocKind :: Dead ) {
887
+ let info = self . get_alloc_info ( id) ;
888
+ if matches ! ( info . kind, AllocKind :: Dead ) {
907
889
throw_ub ! ( PointerUseAfterFree ( id, msg) )
908
890
}
909
- interp_ok ( ( size, align) )
891
+ interp_ok ( ( info . size , info . align ) )
910
892
}
911
893
912
894
fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
@@ -1458,7 +1440,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1458
1440
let ptr = scalar. to_pointer ( self ) ?;
1459
1441
match self . ptr_try_get_alloc_id ( ptr, 0 ) {
1460
1442
Ok ( ( alloc_id, offset, _) ) => {
1461
- let ( size, _align , _kind ) = self . get_alloc_info ( alloc_id) ;
1443
+ let size = self . get_alloc_info ( alloc_id) . size ;
1462
1444
// If the pointer is out-of-bounds, it may be null.
1463
1445
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
1464
1446
offset > size
0 commit comments