Skip to content

Commit 080d3e4

Browse files
committed
properly prevent recursive statics from marking each other
1 parent e23fc79 commit 080d3e4

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

src/eval_context.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
172172
// FIXME: cache these allocs
173173
let ptr = self.memory.allocate(s.len() as u64, 1)?;
174174
self.memory.write_bytes(ptr, s.as_bytes())?;
175-
self.memory.mark_static(ptr.alloc_id, false)?;
175+
self.memory.mark_static_initalized(ptr.alloc_id, false)?;
176176
Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::from_u128(s.len() as u128)))
177177
}
178178

@@ -194,9 +194,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
194194
Str(ref s) => return self.str_to_value(s),
195195

196196
ByteStr(ref bs) => {
197+
// FIXME: cache these allocs
197198
let ptr = self.memory.allocate(bs.len() as u64, 1)?;
198199
self.memory.write_bytes(ptr, bs)?;
199-
self.memory.mark_static(ptr.alloc_id, false)?;
200+
self.memory.mark_static_initalized(ptr.alloc_id, false)?;
200201
PrimVal::Ptr(ptr)
201202
}
202203

@@ -316,16 +317,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
316317
let global_value = self.globals.get_mut(&id)
317318
.expect("global should have been cached (static)");
318319
match global_value.value {
319-
Value::ByRef(ptr) => self.memory.mark_static(ptr.alloc_id, mutable)?,
320+
Value::ByRef(ptr) => self.memory.mark_static_initalized(ptr.alloc_id, mutable)?,
320321
Value::ByVal(val) => if let PrimVal::Ptr(ptr) = val {
321-
self.memory.mark_static(ptr.alloc_id, mutable)?;
322+
self.memory.mark_static_initalized(ptr.alloc_id, mutable)?;
322323
},
323324
Value::ByValPair(val1, val2) => {
324325
if let PrimVal::Ptr(ptr) = val1 {
325-
self.memory.mark_static(ptr.alloc_id, mutable)?;
326+
self.memory.mark_static_initalized(ptr.alloc_id, mutable)?;
326327
}
327328
if let PrimVal::Ptr(ptr) = val2 {
328-
self.memory.mark_static(ptr.alloc_id, mutable)?;
329+
self.memory.mark_static_initalized(ptr.alloc_id, mutable)?;
329330
}
330331
},
331332
}
@@ -870,10 +871,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
870871
Value::ByRef(ptr) => Lvalue::from_ptr(ptr),
871872
_ => {
872873
let ptr = self.alloc_ptr_with_substs(global_val.ty, cid.substs)?;
874+
self.memory.mark_static(ptr.alloc_id);
873875
self.write_value_to_ptr(global_val.value, ptr, global_val.ty)?;
874876
// see comment on `initialized` field
875877
if global_val.initialized {
876-
self.memory.mark_static(ptr.alloc_id, global_val.mutable)?;
878+
self.memory.mark_static_initalized(ptr.alloc_id, global_val.mutable)?;
877879
}
878880
let lval = self.globals.get_mut(&cid).expect("already checked");
879881
*lval = Global {

src/memory.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub struct Allocation {
3838
/// The alignment of the allocation to detect unaligned reads.
3939
pub align: u64,
4040
/// 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
4242
/// allocation is modified or deallocated in the future.
4343
pub static_kind: StaticKind,
4444
}
@@ -152,6 +152,11 @@ impl<'tcx> Function<'tcx> {
152152
pub struct Memory<'a, 'tcx> {
153153
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations)
154154
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>,
155160
/// Number of virtual bytes allocated
156161
memory_usage: u64,
157162
/// Maximum number of virtual bytes that may be allocated
@@ -189,6 +194,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
189194
memory_size: max_memory,
190195
memory_usage: 0,
191196
packed: BTreeSet::new(),
197+
static_alloc: HashSet::new(),
192198
}
193199
}
194200

@@ -624,8 +630,15 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
624630

625631
/// Reading and writing
626632
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> {
629642
// do not use `self.get_mut(alloc_id)` here, because we might have already marked a
630643
// sub-element or have circular pointers (e.g. `Rc`-cycles)
631644
let relocations = match self.alloc_map.get_mut(&alloc_id) {
@@ -645,7 +658,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
645658
};
646659
// recurse into inner allocations
647660
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+
}
649665
}
650666
// put back the relocations
651667
self.alloc_map.get_mut(&alloc_id).expect("checked above").relocations = relocations;

src/vtable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
112112
}
113113
}
114114

115-
self.memory.mark_static(vtable.alloc_id, false)?;
115+
self.memory.mark_static_initalized(vtable.alloc_id, false)?;
116116

117117
Ok(vtable)
118118
}

0 commit comments

Comments
 (0)