Skip to content

Commit 08e0754

Browse files
committed
Store protectors outside Item, pack Tag and Perm
1 parent b004a03 commit 08e0754

File tree

4 files changed

+139
-66
lines changed

4 files changed

+139
-66
lines changed

src/machine.rs

Lines changed: 5 additions & 2 deletions
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
}
@@ -859,7 +862,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
859862
stacked_borrows.borrow_mut().new_call()
860863
});
861864

862-
let extra = FrameData { call_id, catch_unwind: None, timing };
865+
let extra = FrameData { call_id, catch_unwind: None, timing, protected_tags: Vec::new() };
863866
Ok(frame.with_extra(extra))
864867
}
865868

src/shims/panic.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
124124

125125
trace!("handle_stack_pop(extra = {:?}, unwinding = {})", extra, unwinding);
126126
if let Some(stacked_borrows) = &this.machine.stacked_borrows {
127-
stacked_borrows.borrow_mut().end_call(extra.call_id);
127+
let mut sb = stacked_borrows.borrow_mut();
128+
sb.end_call(extra.call_id);
129+
for tag in extra.protected_tags.drain(..) {
130+
sb.protected_tags.remove(&tag);
131+
}
128132
}
129133

130134
// We only care about `catch_panic` if we're unwinding - if we're doing a normal

src/stacked_borrows.rs

Lines changed: 32 additions & 41 deletions
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,
@@ -232,10 +228,6 @@ impl GlobalStateInner {
232228
assert!(self.active_calls.remove(&id));
233229
}
234230

235-
fn is_active(&self, id: CallId) -> bool {
236-
self.active_calls.contains(&id)
237-
}
238-
239231
pub fn base_ptr_tag(&mut self, id: AllocId) -> SbTag {
240232
self.base_ptr_tags.get(&id).copied().unwrap_or_else(|| {
241233
let tag = self.new_ptr();
@@ -332,24 +324,22 @@ impl<'tcx> Stack {
332324
));
333325
}
334326

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

583573
Stacks {
@@ -792,7 +782,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
792782
});
793783
}
794784

795-
let protector = if protect { Some(this.frame().extra.call_id) } else { None };
796785
trace!(
797786
"reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
798787
kind,
@@ -803,6 +792,15 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
803792
size.bytes()
804793
);
805794

795+
// FIXME: This just protects everything, which is wrong. At the very least, we should not
796+
// protect anything that contains an UnsafeCell.
797+
if protect {
798+
this.frame_mut().extra.protected_tags.push(new_tag);
799+
this.machine.stacked_borrows.as_mut().unwrap().get_mut().protected_tags.insert(new_tag);
800+
}
801+
// FIXME: can't hold the current span handle across the borrows of self above
802+
let current_span = &mut this.machine.current_span();
803+
806804
// Update the stacks.
807805
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
808806
// There could be existing unique pointers reborrowed from them that should remain valid!
@@ -839,14 +837,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
839837
} else {
840838
Permission::SharedReadWrite
841839
};
842-
let protector = if frozen {
843-
protector
844-
} else {
845-
// We do not protect inside UnsafeCell.
846-
// This fixes https://github.com/rust-lang/rust/issues/55005.
847-
None
848-
};
849-
let item = Item { perm, tag: new_tag, protector };
840+
let item = Item { perm, tag: new_tag };
850841
let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut();
851842
stacked_borrows.for_each(range, |offset, stack, history, exposed_tags| {
852843
stack.grant(
@@ -872,7 +863,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
872863
.as_mut()
873864
.expect("we should have Stacked Borrows data")
874865
.borrow_mut();
875-
let item = Item { perm, tag: new_tag, protector };
866+
let item = Item { perm, tag: new_tag };
876867
let range = alloc_range(base_offset, size);
877868
let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
878869
let current_span = &mut machine.current_span(); // `get_alloc_extra_mut` invalidated our old `current_span`

0 commit comments

Comments
 (0)