Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 58c79c5

Browse files
committed
tweaks and feedback
1 parent 4fbb284 commit 58c79c5

File tree

5 files changed

+48
-60
lines changed

5 files changed

+48
-60
lines changed

src/machine.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
646646
let alloc: Allocation<Tag, Self::AllocExtra> = alloc.convert_tag_add_extra(
647647
&ecx.tcx,
648648
AllocExtra {
649-
stacked_borrows: stacks,
649+
stacked_borrows: stacks.map(RefCell::new),
650650
data_race: race_alloc,
651651
weak_memory: buffer_alloc,
652652
},
@@ -745,7 +745,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
745745
data_race.read(alloc_id, range, machine.data_race.as_ref().unwrap())?;
746746
}
747747
if let Some(stacked_borrows) = &alloc_extra.stacked_borrows {
748-
stacked_borrows.memory_read(
748+
stacked_borrows.borrow_mut().memory_read(
749749
alloc_id,
750750
tag,
751751
range,
@@ -771,7 +771,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
771771
data_race.write(alloc_id, range, machine.data_race.as_mut().unwrap())?;
772772
}
773773
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
774-
stacked_borrows.memory_written(
774+
stacked_borrows.get_mut().memory_written(
775775
alloc_id,
776776
tag,
777777
range,
@@ -800,7 +800,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
800800
data_race.deallocate(alloc_id, range, machine.data_race.as_mut().unwrap())?;
801801
}
802802
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
803-
stacked_borrows.memory_deallocated(
803+
stacked_borrows.get_mut().memory_deallocated(
804804
alloc_id,
805805
tag,
806806
range,

src/stacked_borrows.rs

Lines changed: 35 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ use diagnostics::{AllocHistory, TagHistory};
2525

2626
pub type PtrId = NonZeroU64;
2727
pub type CallId = NonZeroU64;
28-
pub type AllocExtra = Stacks;
28+
// Even reading memory can have effects on the stack, so we need a `RefCell` here.
29+
pub type AllocExtra = RefCell<Stacks>;
2930

3031
/// Tracking pointer provenance
3132
#[derive(Copy, Clone, Hash, Eq)]
@@ -131,7 +132,7 @@ pub struct Stack {
131132
/// * Above a `SharedReadOnly` there can only be more `SharedReadOnly`.
132133
/// * Except for `Untagged`, no tag occurs in the stack more than once.
133134
borrows: Vec<Item>,
134-
/// If this is `Some(id)`, then the actual current stack is unknown. THis can happen when
135+
/// If this is `Some(id)`, then the actual current stack is unknown. This can happen when
135136
/// wildcard pointers are used to access this location. What we do know is that `borrows` are at
136137
/// the top of the stack, and below it are arbitrarily many items whose `tag` is either
137138
/// `Untagged` or strictly less than `id`.
@@ -144,11 +145,11 @@ pub struct Stack {
144145
#[derive(Clone, Debug)]
145146
pub struct Stacks {
146147
// Even reading memory can have effects on the stack, so we need a `RefCell` here.
147-
stacks: RefCell<RangeMap<Stack>>,
148+
stacks: RangeMap<Stack>,
148149
/// Stores past operations on this allocation
149-
history: RefCell<AllocHistory>,
150+
history: AllocHistory,
150151
/// The set of tags that have been exposed inside this allocation.
151-
exposed_tags: RefCell<FxHashSet<SbTag>>,
152+
exposed_tags: FxHashSet<SbTag>,
152153
}
153154

154155
/// Extra global state, available to the memory access hooks.
@@ -689,34 +690,14 @@ impl<'tcx> Stacks {
689690
let stack = Stack { borrows: vec![item], unknown_bottom: None };
690691

691692
Stacks {
692-
stacks: RefCell::new(RangeMap::new(size, stack)),
693-
history: RefCell::new(AllocHistory::new()),
694-
exposed_tags: RefCell::new(FxHashSet::default()),
693+
stacks: RangeMap::new(size, stack),
694+
history: AllocHistory::new(),
695+
exposed_tags: FxHashSet::default(),
695696
}
696697
}
697698

698699
/// Call `f` on every stack in the range.
699700
fn for_each(
700-
&self,
701-
range: AllocRange,
702-
mut f: impl FnMut(
703-
Size,
704-
&mut Stack,
705-
&mut AllocHistory,
706-
&mut FxHashSet<SbTag>,
707-
) -> InterpResult<'tcx>,
708-
) -> InterpResult<'tcx> {
709-
let mut stacks = self.stacks.borrow_mut();
710-
let history = &mut *self.history.borrow_mut();
711-
let exposed_tags = &mut *self.exposed_tags.borrow_mut();
712-
for (offset, stack) in stacks.iter_mut(range.start, range.size) {
713-
f(offset, stack, history, exposed_tags)?;
714-
}
715-
Ok(())
716-
}
717-
718-
/// Call `f` on every stack in the range.
719-
fn for_each_mut(
720701
&mut self,
721702
range: AllocRange,
722703
mut f: impl FnMut(
@@ -726,11 +707,8 @@ impl<'tcx> Stacks {
726707
&mut FxHashSet<SbTag>,
727708
) -> InterpResult<'tcx>,
728709
) -> InterpResult<'tcx> {
729-
let stacks = self.stacks.get_mut();
730-
let history = &mut *self.history.get_mut();
731-
let exposed_tags = self.exposed_tags.get_mut();
732-
for (offset, stack) in stacks.iter_mut(range.start, range.size) {
733-
f(offset, stack, history, exposed_tags)?;
710+
for (offset, stack) in self.stacks.iter_mut(range.start, range.size) {
711+
f(offset, stack, &mut self.history, &mut self.exposed_tags)?;
734712
}
735713
Ok(())
736714
}
@@ -777,8 +755,8 @@ impl Stacks {
777755
(tag, Permission::SharedReadWrite)
778756
}
779757
};
780-
let stacks = Stacks::new(size, perm, base_tag);
781-
stacks.history.borrow_mut().log_creation(
758+
let mut stacks = Stacks::new(size, perm, base_tag);
759+
stacks.history.log_creation(
782760
None,
783761
base_tag,
784762
alloc_range(Size::ZERO, size),
@@ -789,7 +767,7 @@ impl Stacks {
789767

790768
#[inline(always)]
791769
pub fn memory_read<'tcx>(
792-
&self,
770+
&mut self,
793771
alloc_id: AllocId,
794772
tag: SbTagExtra,
795773
range: AllocRange,
@@ -832,7 +810,7 @@ impl Stacks {
832810
range.size.bytes()
833811
);
834812
let mut state = state.borrow_mut();
835-
self.for_each_mut(range, |offset, stack, history, exposed_tags| {
813+
self.for_each(range, |offset, stack, history, exposed_tags| {
836814
stack.access(
837815
AccessKind::Write,
838816
tag,
@@ -855,7 +833,7 @@ impl Stacks {
855833
) -> InterpResult<'tcx> {
856834
trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, range.size.bytes());
857835
let state = state.borrow();
858-
self.for_each_mut(range, |offset, stack, history, exposed_tags| {
836+
self.for_each(range, |offset, stack, history, exposed_tags| {
859837
stack.dealloc(tag, (alloc_id, range, offset), &state, history, exposed_tags)
860838
})?;
861839
Ok(())
@@ -890,17 +868,19 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
890868
return Ok(())
891869
};
892870
let extra = this.get_alloc_extra(alloc_id)?;
893-
let stacked_borrows =
894-
extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data");
895-
let mut alloc_history = stacked_borrows.history.borrow_mut();
896-
alloc_history.log_creation(
871+
let mut stacked_borrows = extra
872+
.stacked_borrows
873+
.as_ref()
874+
.expect("we should have Stacked Borrows data")
875+
.borrow_mut();
876+
stacked_borrows.history.log_creation(
897877
Some(orig_tag),
898878
new_tag,
899879
alloc_range(base_offset, size),
900880
current_span,
901881
);
902882
if protect {
903-
alloc_history.log_protector(orig_tag, new_tag, current_span);
883+
stacked_borrows.history.log_protector(orig_tag, new_tag, current_span);
904884
}
905885
Ok(())
906886
};
@@ -976,8 +956,11 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
976956
// We have to use shared references to alloc/memory_extra here since
977957
// `visit_freeze_sensitive` needs to access the global state.
978958
let extra = this.get_alloc_extra(alloc_id)?;
979-
let stacked_borrows =
980-
extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data");
959+
let mut stacked_borrows = extra
960+
.stacked_borrows
961+
.as_ref()
962+
.expect("we should have Stacked Borrows data")
963+
.borrow_mut();
981964
this.visit_freeze_sensitive(place, size, |mut range, frozen| {
982965
// Adjust range.
983966
range.start += base_offset;
@@ -1015,13 +998,16 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1015998
// Note that this asserts that the allocation is mutable -- but since we are creating a
1016999
// mutable pointer, that seems reasonable.
10171000
let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
1018-
let stacked_borrows =
1019-
alloc_extra.stacked_borrows.as_mut().expect("we should have Stacked Borrows data");
1001+
let mut stacked_borrows = alloc_extra
1002+
.stacked_borrows
1003+
.as_mut()
1004+
.expect("we should have Stacked Borrows data")
1005+
.borrow_mut();
10201006
let item = Item { perm, tag: new_tag, protector };
10211007
let range = alloc_range(base_offset, size);
10221008
let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
10231009
let current_span = &mut machine.current_span(); // `get_alloc_extra_mut` invalidated our old `current_span`
1024-
stacked_borrows.for_each_mut(range, |offset, stack, history, exposed_tags| {
1010+
stacked_borrows.for_each(range, |offset, stack, history, exposed_tags| {
10251011
stack.grant(
10261012
orig_tag,
10271013
item,
@@ -1177,7 +1163,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
11771163
match this.get_alloc_extra(alloc_id) {
11781164
Ok(alloc_extra) => {
11791165
trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id}");
1180-
alloc_extra.stacked_borrows.as_ref().unwrap().exposed_tags.borrow_mut().insert(tag);
1166+
alloc_extra.stacked_borrows.as_ref().unwrap().borrow_mut().exposed_tags.insert(tag);
11811167
}
11821168
Err(err) => {
11831169
trace!(

src/stacked_borrows/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,6 @@ fn error_cause(stack: &Stack, tag: SbTagExtra) -> &'static str {
259259
", but that tag does not exist in the borrow stack for this location"
260260
}
261261
} else {
262-
", but no exposed tags are valid in the borrow stack for this location"
262+
", but no exposed tags have suitable permission in the borrow stack for this location"
263263
}
264264
}

tests/fail/stacked_borrows/exposed_only_ro.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: Undefined Behavior: attempting a write access using <wildcard> at ALLOC[0x0], but no exposed tags are valid in the borrow stack for this location
1+
error: Undefined Behavior: attempting a write access using <wildcard> at ALLOC[0x0], but no exposed tags have suitable permission in the borrow stack for this location
22
--> $DIR/exposed_only_ro.rs:LL:CC
33
|
44
LL | unsafe { *ptr = 0 };
55
| ^^^^^^^^
66
| |
7-
| attempting a write access using <wildcard> at ALLOC[0x0], but no exposed tags are valid in the borrow stack for this location
7+
| attempting a write access using <wildcard> at ALLOC[0x0], but no exposed tags have suitable permission in the borrow stack for this location
88
| this error occurs as part of an access at ALLOC[0x0..0x4]
99
|
1010
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental

tests/fail/stacked_borrows/illegal_read_despite_exposed2.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ fn main() {
77
let exposed_ptr = addr as *mut i32;
88
// From the exposed ptr, we get a new unique ptr.
99
let root2 = &mut *exposed_ptr;
10-
// let _fool = root2 as *mut _; // this would [fool] us, since SRW(N+1) remains on the stack
11-
// Stack: Unknown(<N), Unique(N) [, SRW(N+1)]
10+
// let _fool = root2 as *mut _; // this would fool us, since SRW(N+1) remains on the stack
11+
// Stack: Unknown(<N), Unique(N)
12+
// Stack if _fool existed: Unknown(<N), Unique(N), SRW(N+1)
1213
// And we test that it has uniqueness by doing a conflicting read.
1314
let _val = *exposed_ptr;
14-
// Stack: Unknown(<N), Disabled(N) [, SRW(N+1)]
15-
// collapsed to Unknown(<N) [Unknown(<N+2)]
15+
// Stack: Unknown(<N), Disabled(N)
16+
// collapsed to Unknown(<N)
17+
// Stack if _fool existed: Unknown(<N), Disabled(N), SRW(N+1); collapsed to Unknown(<N+2) which would not cause an ERROR
1618
let _val = *root2; //~ ERROR: borrow stack
1719
}
1820
}

0 commit comments

Comments
 (0)