diff options
| author | Ralf Jung <post@ralfj.de> | 2025-05-05 11:58:34 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-05 11:58:34 +0000 |
| commit | 70ef2504b95f25e38671cb7b900f0879c29e0ecc (patch) | |
| tree | c145cb845e27a2724fffafc07adc86b1425a8c38 | |
| parent | f8a8bbd4c00f29ba4766edd20199190b2bb9135e (diff) | |
| parent | 45d4bb2541c240087c86fa1eb742c04feabe9392 (diff) | |
| download | rust-70ef2504b95f25e38671cb7b900f0879c29e0ecc.tar.gz rust-70ef2504b95f25e38671cb7b900f0879c29e0ecc.zip | |
Merge pull request #4306 from yoctocell/fix-unsafecell-inside-box
Tree Borrows: Correctly handle interior mutable data in `Box`
3 files changed, 43 insertions, 1 deletions
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 20f06a3acbd..f3e32e75f2f 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -168,7 +168,7 @@ impl<'tcx> NewPermission { pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| { // Regular `Unpin` box, give it `noalias` but only a weak protector // because it is valid to deallocate it within the function. - let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env()); + let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); let protected = kind == RetagKind::FnEntry; let initial_state = Permission::new_reserved(ty_is_freeze, protected); Self { diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs b/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs new file mode 100644 index 00000000000..adf2f4e845b --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs @@ -0,0 +1,35 @@ +//@compile-flags: -Zmiri-tree-borrows +#![feature(box_as_ptr)] +#[path = "../../utils/mod.rs"] +#[macro_use] +mod utils; + +use std::cell::UnsafeCell; + +pub fn main() { + let cell = UnsafeCell::new(42); + let box1 = Box::new(cell); + + unsafe { + let ptr1: *mut UnsafeCell<i32> = Box::into_raw(box1); + name!(ptr1); + + let mut box2 = Box::from_raw(ptr1); + // `ptr2` will be a descendant of `ptr1`. + let ptr2: *mut UnsafeCell<i32> = Box::as_mut_ptr(&mut box2); + name!(ptr2); + + // We perform a write through `x`. + // Because `ptr1` is ReservedIM, a child write will make it transition to Active. + // Because `ptr2` is ReservedIM, a foreign write doesn't have any effect on it. + let x = (*ptr1).get(); + *x = 1; + + // We can still read from `ptr2`. + let val = *(*ptr2).get(); + assert_eq!(val, 1); + + let alloc_id = alloc_id!(ptr1); + print_state!(alloc_id); + } +} diff --git a/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.stderr b/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.stderr new file mode 100644 index 00000000000..5dbfff718b1 --- /dev/null +++ b/src/tools/miri/tests/pass/tree_borrows/cell-inside-box.stderr @@ -0,0 +1,7 @@ +────────────────────────────────────────────────── +Warning: this tree is indicative only. Some tags may have been hidden. +0.. 4 +| Act | └─┬──<TAG=root of the allocation> +| Act | └─┬──<TAG=ptr1> +| ReIM| └────<TAG=ptr2> +────────────────────────────────────────────────── |
