Skip to content

Commit ce3f0d2

Browse files
committed
Add strong mode for tree borrows
1 parent e7da309 commit ce3f0d2

File tree

7 files changed

+90
-1
lines changed

7 files changed

+90
-1
lines changed

src/bin/miri.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,14 @@ fn main() {
518518
miri_config.borrow_tracker =
519519
Some(BorrowTrackerMethod::TreeBorrows(TreeBorrowsParams {
520520
precise_interior_mut: true,
521+
start_mut_ref_on_fn_entry_as_active: false,
522+
}));
523+
miri_config.provenance_mode = ProvenanceMode::Strict;
524+
} else if arg == "-Zmiri-tree-borrows-strong" {
525+
miri_config.borrow_tracker =
526+
Some(BorrowTrackerMethod::TreeBorrows(TreeBorrowsParams {
527+
precise_interior_mut: true,
528+
start_mut_ref_on_fn_entry_as_active: true,
521529
}));
522530
miri_config.provenance_mode = ProvenanceMode::Strict;
523531
} else if arg == "-Zmiri-tree-borrows-no-precise-interior-mut" {

src/borrow_tracker/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ pub enum BorrowTrackerMethod {
233233
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
234234
pub struct TreeBorrowsParams {
235235
pub precise_interior_mut: bool,
236+
pub start_mut_ref_on_fn_entry_as_active: bool,
236237
}
237238

238239
impl BorrowTrackerMethod {

src/borrow_tracker/tree_borrows/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,16 @@ impl<'tcx> NewPermission {
146146
let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env());
147147
let is_protected = retag_kind == RetagKind::FnEntry;
148148

149+
let start_mut_ref_on_fn_entry_as_active = cx
150+
.machine
151+
.borrow_tracker
152+
.as_ref()
153+
.unwrap()
154+
.borrow()
155+
.borrow_tracker_method
156+
.get_tree_borrows_params()
157+
.start_mut_ref_on_fn_entry_as_active;
158+
149159
if matches!(ref_mutability, Some(Mutability::Mut) | None if !ty_is_unpin) {
150160
// Mutable reference / Box to pinning type: retagging is a NOP.
151161
// FIXME: with `UnsafePinned`, this should do proper per-byte tracking.
@@ -155,6 +165,9 @@ impl<'tcx> NewPermission {
155165
let freeze_perm = match ref_mutability {
156166
// Shared references are frozen.
157167
Some(Mutability::Not) => Permission::new_frozen(),
168+
// Mutable references on fn entry are activated based on config
169+
Some(Mutability::Mut) if start_mut_ref_on_fn_entry_as_active && is_protected =>
170+
Permission::new_active(),
158171
// Mutable references and Boxes are reserved.
159172
_ => Permission::new_reserved_frz(),
160173
};

src/borrow_tracker/tree_borrows/perms.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl PartialOrd for PermissionPriv {
9090
impl PermissionPriv {
9191
/// Check if `self` can be the initial state of a pointer.
9292
fn is_initial(&self) -> bool {
93-
matches!(self, ReservedFrz { conflicted: false } | Frozen | ReservedIM | Cell)
93+
matches!(self, ReservedFrz { conflicted: false } | Frozen | ReservedIM | Cell | Active)
9494
}
9595

9696
/// Reject `ReservedIM` that cannot exist in the presence of a protector.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@revisions: stack tree
2+
//@[tree]compile-flags: -Zmiri-tree-borrows-strong
3+
4+
fn may_insert_spurious_write(_x: &mut u32) {}
5+
6+
fn main() {
7+
let target = &mut 42;
8+
let target_alias = &*target;
9+
let target_alias_ptr = target_alias as *const _;
10+
may_insert_spurious_write(target);
11+
// now `target_alias` is invalid
12+
let _val = unsafe { *target_alias_ptr };
13+
//~[stack]^ ERROR: /read access .* tag does not exist in the borrow stack/
14+
//~[tree]| ERROR: /read access through .* is forbidden/
15+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error: Undefined Behavior: attempting a read access using <TAG> at ALLOC[0x0], but that tag does not exist in the borrow stack for this location
2+
--> tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
3+
|
4+
LL | let _val = unsafe { *target_alias_ptr };
5+
| ^^^^^^^^^^^^^^^^^ this error occurs as part of an access at ALLOC[0x0..0x4]
6+
|
7+
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
8+
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
9+
help: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x4]
10+
--> tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
11+
|
12+
LL | let target_alias_ptr = target_alias as *const _;
13+
| ^^^^^^^^^^^^
14+
help: <TAG> was later invalidated at offsets [0x0..0x4] by a Unique function-entry retag inside this call
15+
--> tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
16+
|
17+
LL | may_insert_spurious_write(target);
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
= note: BACKTRACE (of the first span):
20+
= note: inside `main` at tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
21+
22+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
23+
24+
error: aborting due to 1 previous error
25+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: Undefined Behavior: read access through <TAG> at ALLOC[0x0] is forbidden
2+
--> tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
3+
|
4+
LL | let _val = unsafe { *target_alias_ptr };
5+
| ^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
6+
|
7+
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
8+
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
9+
= help: the accessed tag <TAG> has state Disabled which forbids this child read access
10+
help: the accessed tag <TAG> was created here, in the initial state Frozen
11+
--> tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
12+
|
13+
LL | let target_alias = &*target;
14+
| ^^^^^^^^
15+
help: the accessed tag <TAG> later transitioned to Disabled due to a protector release (acting as a foreign write access) on every location previously accessed by this tag
16+
--> tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
17+
|
18+
LL | fn may_insert_spurious_write(_x: &mut u32) {}
19+
| ^
20+
= help: this transition corresponds to a loss of read permissions
21+
= note: BACKTRACE (of the first span):
22+
= note: inside `main` at tests/fail/both_borrows/spurious_write_may_be_added.rs:LL:CC
23+
24+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
25+
26+
error: aborting due to 1 previous error
27+

0 commit comments

Comments
 (0)