about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-05-05 11:58:34 +0000
committerGitHub <noreply@github.com>2025-05-05 11:58:34 +0000
commit70ef2504b95f25e38671cb7b900f0879c29e0ecc (patch)
treec145cb845e27a2724fffafc07adc86b1425a8c38
parentf8a8bbd4c00f29ba4766edd20199190b2bb9135e (diff)
parent45d4bb2541c240087c86fa1eb742c04feabe9392 (diff)
downloadrust-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`
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs2
-rw-r--r--src/tools/miri/tests/pass/tree_borrows/cell-inside-box.rs35
-rw-r--r--src/tools/miri/tests/pass/tree_borrows/cell-inside-box.stderr7
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>
+──────────────────────────────────────────────────