@@ -38,7 +38,7 @@ pub struct Allocation {
38
38
/// The alignment of the allocation to detect unaligned reads.
39
39
pub align : u64 ,
40
40
/// Whether the allocation may be modified.
41
- /// Use the `mark_static ` method of `Memory` to ensure that an error occurs, if the memory of this
41
+ /// Use the `mark_static_initalized ` method of `Memory` to ensure that an error occurs, if the memory of this
42
42
/// allocation is modified or deallocated in the future.
43
43
pub static_kind : StaticKind ,
44
44
}
@@ -152,6 +152,11 @@ impl<'tcx> Function<'tcx> {
152
152
pub struct Memory < ' a , ' tcx > {
153
153
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations)
154
154
alloc_map : HashMap < AllocId , Allocation > ,
155
+ /// Set of statics, constants, promoteds, vtables, ... to prevent `mark_static_initalized` from stepping
156
+ /// out of its own allocations.
157
+ /// This set only contains statics backed by an allocation. If they are ByVal or ByValPair they
158
+ /// are not here, but will be inserted once they become ByRef.
159
+ static_alloc : HashSet < AllocId > ,
155
160
/// Number of virtual bytes allocated
156
161
memory_usage : u64 ,
157
162
/// Maximum number of virtual bytes that may be allocated
@@ -189,6 +194,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
189
194
memory_size : max_memory,
190
195
memory_usage : 0 ,
191
196
packed : BTreeSet :: new ( ) ,
197
+ static_alloc : HashSet :: new ( ) ,
192
198
}
193
199
}
194
200
@@ -624,8 +630,15 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
624
630
625
631
/// Reading and writing
626
632
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
627
- /// mark an allocation as static, either mutable or not
628
- pub fn mark_static ( & mut self , alloc_id : AllocId , mutable : bool ) -> EvalResult < ' tcx > {
633
+ /// mark an allocation as being the entry point to a static (see `static_alloc` field)
634
+ pub fn mark_static ( & mut self , alloc_id : AllocId ) {
635
+ if !self . static_alloc . insert ( alloc_id) {
636
+ bug ! ( "tried to mark an allocation ({:?}) as static twice" , alloc_id) ;
637
+ }
638
+ }
639
+
640
+ /// mark an allocation as static and initialized, either mutable or not
641
+ pub fn mark_static_initalized ( & mut self , alloc_id : AllocId , mutable : bool ) -> EvalResult < ' tcx > {
629
642
// do not use `self.get_mut(alloc_id)` here, because we might have already marked a
630
643
// sub-element or have circular pointers (e.g. `Rc`-cycles)
631
644
let relocations = match self . alloc_map . get_mut ( & alloc_id) {
@@ -645,7 +658,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
645
658
} ;
646
659
// recurse into inner allocations
647
660
for & alloc in relocations. values ( ) {
648
- self . mark_static ( alloc, mutable) ?;
661
+ // relocations into other statics are not "inner allocations"
662
+ if !self . static_alloc . contains ( & alloc) {
663
+ self . mark_static_initalized ( alloc, mutable) ?;
664
+ }
649
665
}
650
666
// put back the relocations
651
667
self . alloc_map . get_mut ( & alloc_id) . expect ( "checked above" ) . relocations = relocations;
0 commit comments