@@ -72,6 +72,21 @@ pub enum AllocKind {
72
72
Dead ,
73
73
}
74
74
75
+ /// Metadata about an `AllocId`.
76
+ #[ derive( Copy , Clone , PartialEq , Debug ) ]
77
+ pub struct AllocInfo {
78
+ pub size : Size ,
79
+ pub align : Align ,
80
+ pub kind : AllocKind ,
81
+ pub mutbl : Mutability ,
82
+ }
83
+
84
+ impl AllocInfo {
85
+ fn new ( size : Size , align : Align , kind : AllocKind , mutbl : Mutability ) -> Self {
86
+ Self { size, align, kind, mutbl }
87
+ }
88
+ }
89
+
75
90
/// The value of a function pointer.
76
91
#[ derive( Debug , Copy , Clone ) ]
77
92
pub enum FnVal < ' tcx , Other > {
@@ -524,17 +539,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
524
539
match self . ptr_try_get_alloc_id ( ptr, 0 ) {
525
540
Err ( addr) => is_offset_misaligned ( addr, align) ,
526
541
Ok ( ( alloc_id, offset, _prov) ) => {
527
- let ( _size, alloc_align, kind, _mutbl) = self . get_alloc_info ( alloc_id) ;
528
- if let Some ( misalign) =
529
- M :: alignment_check ( self , alloc_id, alloc_align, kind, offset, align)
530
- {
542
+ let alloc_info = self . get_alloc_info ( alloc_id) ;
543
+ if let Some ( misalign) = M :: alignment_check (
544
+ self ,
545
+ alloc_id,
546
+ alloc_info. align ,
547
+ alloc_info. kind ,
548
+ offset,
549
+ align,
550
+ ) {
531
551
Some ( misalign)
532
552
} else if M :: Provenance :: OFFSET_IS_ADDR {
533
553
is_offset_misaligned ( ptr. addr ( ) . bytes ( ) , align)
534
554
} else {
535
555
// Check allocation alignment and offset alignment.
536
- if alloc_align . bytes ( ) < align. bytes ( ) {
537
- Some ( Misalignment { has : alloc_align , required : align } )
556
+ if alloc_info . align . bytes ( ) < align. bytes ( ) {
557
+ Some ( Misalignment { has : alloc_info . align , required : align } )
538
558
} else {
539
559
is_offset_misaligned ( offset. bytes ( ) , align)
540
560
}
@@ -818,19 +838,24 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
818
838
819
839
/// Obtain the size and alignment of an allocation, even if that allocation has
820
840
/// been deallocated.
821
- pub fn get_alloc_info ( & self , id : AllocId ) -> ( Size , Align , AllocKind , Mutability ) {
841
+ pub fn get_alloc_info ( & self , id : AllocId ) -> AllocInfo {
822
842
// # Regular allocations
823
843
// Don't use `self.get_raw` here as that will
824
844
// a) cause cycles in case `id` refers to a static
825
845
// b) duplicate a global's allocation in miri
826
846
if let Some ( ( _, alloc) ) = self . memory . alloc_map . get ( id) {
827
- return ( alloc. size ( ) , alloc. align , AllocKind :: LiveData , alloc. mutability ) ;
847
+ return AllocInfo :: new (
848
+ alloc. size ( ) ,
849
+ alloc. align ,
850
+ AllocKind :: LiveData ,
851
+ alloc. mutability ,
852
+ ) ;
828
853
}
829
854
830
855
// # Function pointers
831
856
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
832
857
if self . get_fn_alloc ( id) . is_some ( ) {
833
- return ( Size :: ZERO , Align :: ONE , AllocKind :: Function , Mutability :: Not ) ;
858
+ return AllocInfo :: new ( Size :: ZERO , Align :: ONE , AllocKind :: Function , Mutability :: Not ) ;
834
859
}
835
860
836
861
// # Statics
@@ -852,7 +877,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
852
877
// succeeds, as the query is fed at DefId creation time, so no
853
878
// evaluation actually occurs.
854
879
let alloc = self . tcx . eval_static_initializer ( def_id) . unwrap ( ) ;
855
- ( alloc. 0 . size ( ) , alloc. 0 . align , alloc. 0 . mutability )
880
+ // Nested statics in a `static` are never interior mutable, so just use the
881
+ // declared mutability, which should be equal to the allocation's mutability.
882
+ assert_eq ! ( mutability, alloc. 0 . mutability) ;
883
+ ( alloc. 0 . size ( ) , alloc. 0 . align , mutability)
856
884
} else {
857
885
// Use size and align of the type for everything else. We need
858
886
// to do that to
@@ -873,20 +901,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
873
901
} ;
874
902
( layout. size , layout. align . abi , mutability)
875
903
} ;
876
- ( size, align, AllocKind :: LiveData , mutability)
904
+ AllocInfo :: new ( size, align, AllocKind :: LiveData , mutability)
877
905
}
878
906
Some ( GlobalAlloc :: Memory ( alloc) ) => {
879
907
// Need to duplicate the logic here, because the global allocations have
880
908
// different associated types than the interpreter-local ones.
881
909
let alloc = alloc. inner ( ) ;
882
- ( alloc. size ( ) , alloc. align , AllocKind :: LiveData , alloc. mutability )
910
+ AllocInfo :: new ( alloc. size ( ) , alloc. align , AllocKind :: LiveData , alloc. mutability )
883
911
}
884
912
Some ( GlobalAlloc :: Function { .. } ) => {
885
913
bug ! ( "We already checked function pointers above" )
886
914
}
887
915
Some ( GlobalAlloc :: VTable ( ..) ) => {
888
916
// No data to be accessed here. But vtables are pointer-aligned.
889
- return (
917
+ return AllocInfo :: new (
890
918
Size :: ZERO ,
891
919
self . tcx . data_layout . pointer_align . abi ,
892
920
AllocKind :: VTable ,
@@ -902,7 +930,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
902
930
. dead_alloc_map
903
931
. get ( & id)
904
932
. expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) ;
905
- ( size, align, AllocKind :: Dead , Mutability :: Not )
933
+ AllocInfo :: new ( size, align, AllocKind :: Dead , Mutability :: Not )
906
934
}
907
935
}
908
936
}
@@ -913,11 +941,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
913
941
id : AllocId ,
914
942
msg : CheckInAllocMsg ,
915
943
) -> InterpResult < ' tcx , ( Size , Align ) > {
916
- let ( size , align , kind , _mutbl ) = self . get_alloc_info ( id) ;
917
- if matches ! ( kind, AllocKind :: Dead ) {
944
+ let info = self . get_alloc_info ( id) ;
945
+ if matches ! ( info . kind, AllocKind :: Dead ) {
918
946
throw_ub ! ( PointerUseAfterFree ( id, msg) )
919
947
}
920
- interp_ok ( ( size, align) )
948
+ interp_ok ( ( info . size , info . align ) )
921
949
}
922
950
923
951
fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
@@ -1469,7 +1497,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
1469
1497
let ptr = scalar. to_pointer ( self ) ?;
1470
1498
match self . ptr_try_get_alloc_id ( ptr, 0 ) {
1471
1499
Ok ( ( alloc_id, offset, _) ) => {
1472
- let ( size, _align , _kind , _mutbl ) = self . get_alloc_info ( alloc_id) ;
1500
+ let size = self . get_alloc_info ( alloc_id) . size ;
1473
1501
// If the pointer is out-of-bounds, it may be null.
1474
1502
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
1475
1503
offset > size
0 commit comments