Skip to content

Commit 85d3a5d

Browse files
committed
Store protectors outside Item, pack Tag and Perm
1 parent 984b46c commit 85d3a5d

File tree

3 files changed

+139
-66
lines changed

3 files changed

+139
-66
lines changed

src/machine.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,18 @@ pub struct FrameData<'tcx> {
5454
/// for the start of this frame. When we finish executing this frame,
5555
/// we use this to register a completed event with `measureme`.
5656
pub timing: Option<measureme::DetachedTiming>,
57+
58+
pub protected_tags: Vec<SbTag>,
5759
}
5860

5961
impl<'tcx> std::fmt::Debug for FrameData<'tcx> {
6062
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6163
// Omitting `timing`, it does not support `Debug`.
62-
let FrameData { call_id, catch_unwind, timing: _ } = self;
64+
let FrameData { call_id, catch_unwind, timing: _, protected_tags } = self;
6365
f.debug_struct("FrameData")
6466
.field("call_id", call_id)
6567
.field("catch_unwind", catch_unwind)
68+
.field("protected_tags", protected_tags)
6669
.finish()
6770
}
6871
}
@@ -887,7 +890,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
887890
stacked_borrows.borrow_mut().new_call()
888891
});
889892

890-
let extra = FrameData { call_id, catch_unwind: None, timing };
893+
let extra = FrameData { call_id, catch_unwind: None, timing, protected_tags: Vec::new() };
891894
Ok(frame.with_extra(extra))
892895
}
893896

@@ -931,7 +934,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
931934
) -> InterpResult<'tcx, StackPopJump> {
932935
let timing = frame.extra.timing.take();
933936
if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
934-
stacked_borrows.borrow_mut().end_call(frame.extra.call_id);
937+
let mut sb = stacked_borrows.borrow_mut();
938+
sb.end_call(frame.extra.call_id);
939+
for tag in frame.extra.protected_tags.drain(..) {
940+
sb.protected_tags.remove(&tag);
941+
}
935942
}
936943
let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
937944
if let Some(profiler) = ecx.machine.profiler.as_ref() {

src/stacked_borrows.rs

+32-41
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,11 @@ pub struct Item {
9999
perm: Permission,
100100
/// The pointers the permission is granted to.
101101
tag: SbTag,
102-
/// An optional protector, ensuring the item cannot get popped until `CallId` is over.
103-
protector: Option<CallId>,
104102
}
105103

106104
impl fmt::Debug for Item {
107105
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108-
write!(f, "[{:?} for {:?}", self.perm, self.tag)?;
109-
if let Some(call) = self.protector {
110-
write!(f, " (call {})", call)?;
111-
}
112-
write!(f, "]")?;
113-
Ok(())
106+
write!(f, "[{:?} for {:?}]", self.perm, self.tag)
114107
}
115108
}
116109

@@ -138,6 +131,8 @@ pub struct GlobalStateInner {
138131
next_call_id: CallId,
139132
/// Those call IDs corresponding to functions that are still running.
140133
active_calls: FxHashSet<CallId>,
134+
/// All tags currently protected
135+
pub(crate) protected_tags: FxHashSet<SbTag>,
141136
/// The pointer ids to trace
142137
tracked_pointer_tags: HashSet<SbTag>,
143138
/// The call ids to trace
@@ -202,6 +197,7 @@ impl GlobalStateInner {
202197
base_ptr_tags: FxHashMap::default(),
203198
next_call_id: NonZeroU64::new(1).unwrap(),
204199
active_calls: FxHashSet::default(),
200+
protected_tags: FxHashSet::default(),
205201
tracked_pointer_tags,
206202
tracked_call_ids,
207203
retag_fields,
@@ -230,10 +226,6 @@ impl GlobalStateInner {
230226
assert!(self.active_calls.remove(&id));
231227
}
232228

233-
fn is_active(&self, id: CallId) -> bool {
234-
self.active_calls.contains(&id)
235-
}
236-
237229
pub fn base_ptr_tag(&mut self, id: AllocId) -> SbTag {
238230
self.base_ptr_tags.get(&id).copied().unwrap_or_else(|| {
239231
let tag = self.new_ptr();
@@ -333,24 +325,22 @@ impl<'tcx> Stack {
333325
));
334326
}
335327

336-
if let Some(call) = item.protector {
337-
if global.is_active(call) {
338-
if let Some((tag, _alloc_range, _offset, _access)) = provoking_access {
339-
Err(err_sb_ub(
340-
format!(
341-
"not granting access to tag {:?} because incompatible item is protected: {:?}",
342-
tag, item
343-
),
344-
None,
345-
tag.and_then(|tag| alloc_history.get_logs_relevant_to(tag, Some(item.tag))),
346-
))?
347-
} else {
348-
Err(err_sb_ub(
349-
format!("deallocating while item is protected: {:?}", item),
350-
None,
351-
None,
352-
))?
353-
}
328+
if global.protected_tags.contains(&item.tag) {
329+
if let Some((tag, _alloc_range, _offset, _access)) = provoking_access {
330+
Err(err_sb_ub(
331+
format!(
332+
"not granting access to tag {:?} because incompatible item is protected: {:?}",
333+
tag, item
334+
),
335+
None,
336+
tag.and_then(|tag| alloc_history.get_logs_relevant_to(tag, Some(item.tag))),
337+
))?
338+
} else {
339+
Err(err_sb_ub(
340+
format!("deallocating while item is protected: {:?}", item),
341+
None,
342+
None,
343+
))?
354344
}
355345
}
356346
Ok(())
@@ -578,7 +568,7 @@ impl<'tcx> Stack {
578568
impl<'tcx> Stacks {
579569
/// Creates new stack with initial tag.
580570
fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
581-
let item = Item { perm, tag, protector: None };
571+
let item = Item { perm, tag };
582572
let stack = Stack::new(item);
583573

584574
Stacks {
@@ -808,7 +798,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
808798
});
809799
}
810800

811-
let protector = if protect { Some(this.frame().extra.call_id) } else { None };
812801
trace!(
813802
"reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
814803
kind,
@@ -819,6 +808,15 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
819808
size.bytes()
820809
);
821810

811+
// FIXME: This just protects everything, which is wrong. At the very least, we should not
812+
// protect anything that contains an UnsafeCell.
813+
if protect {
814+
this.frame_mut().extra.protected_tags.push(new_tag);
815+
this.machine.stacked_borrows.as_mut().unwrap().get_mut().protected_tags.insert(new_tag);
816+
}
817+
// FIXME: can't hold the current span handle across the borrows of self above
818+
let current_span = &mut this.machine.current_span();
819+
822820
// Update the stacks.
823821
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
824822
// There could be existing unique pointers reborrowed from them that should remain valid!
@@ -855,14 +853,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
855853
} else {
856854
Permission::SharedReadWrite
857855
};
858-
let protector = if frozen {
859-
protector
860-
} else {
861-
// We do not protect inside UnsafeCell.
862-
// This fixes https://github.com/rust-lang/rust/issues/55005.
863-
None
864-
};
865-
let item = Item { perm, tag: new_tag, protector };
856+
let item = Item { perm, tag: new_tag };
866857
let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut();
867858
stacked_borrows.for_each(range, |offset, stack, history, exposed_tags| {
868859
stack.grant(
@@ -888,7 +879,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
888879
.as_mut()
889880
.expect("we should have Stacked Borrows data")
890881
.borrow_mut();
891-
let item = Item { perm, tag: new_tag, protector };
882+
let item = Item { perm, tag: new_tag };
892883
let range = alloc_range(base_offset, size);
893884
let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
894885
let current_span = &mut machine.current_span(); // `get_alloc_extra_mut` invalidated our old `current_span`

0 commit comments

Comments
 (0)