about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-10-19 14:54:23 +0000
committerbors <bors@rust-lang.org>2022-10-19 14:54:23 +0000
commit43de83e02d50c85ccf427ca64c2a0ca2f77161ad (patch)
treebb2c9b50e6954a833c95f6c914e0da070c379ef4
parent4207f9e088dd574827aa35c3273cceee712820a9 (diff)
parente7faf046c0aca0438d948461b8a39046281248ea (diff)
downloadrust-43de83e02d50c85ccf427ca64c2a0ca2f77161ad.tar.gz
rust-43de83e02d50c85ccf427ca64c2a0ca2f77161ad.zip
Auto merge of #2600 - saethlin:ice, r=RalfJung
Fix ICE when trying to GC a Stack with an unknown bottom

Fixes https://github.com/rust-lang/rust/issues/103167

`@RalfJung` I prefer this approach because the whole GC system is sloppy already in order to be efficient (doesn't run often, ignores small stacks) so a bit more imprecision for a simple implementation seems worth it to me. But I'm of course willing to be convinced otherwise.
-rw-r--r--src/tools/miri/src/stacked_borrows/stack.rs12
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs21
2 files changed, 29 insertions, 4 deletions
diff --git a/src/tools/miri/src/stacked_borrows/stack.rs b/src/tools/miri/src/stacked_borrows/stack.rs
index 07c211512f8..aa549e34c5f 100644
--- a/src/tools/miri/src/stacked_borrows/stack.rs
+++ b/src/tools/miri/src/stacked_borrows/stack.rs
@@ -43,10 +43,14 @@ impl Stack {
     pub fn retain(&mut self, tags: &FxHashSet<SbTag>) {
         let mut first_removed = None;
 
-        // For stacks with a known bottom, we never consider removing the bottom-most tag, because
-        // that is the base tag which exists whether or not there are any pointers to the
-        // allocation.
-        let mut read_idx = if self.unknown_bottom.is_some() { 0 } else { 1 };
+        // We never consider removing the bottom-most tag. For stacks without an unknown
+        // bottom this preserves the base tag.
+        // Note that the algorithm below is based on considering the tag at read_idx - 1,
+        // so precisely considering the tag at index 0 for removal when we have an unknown
+        // bottom would complicate the implementation. The simplification of not considering
+        // it does not have a significant impact on the degree to which the GC mititages
+        // memory growth.
+        let mut read_idx = 1;
         let mut write_idx = read_idx;
         while read_idx < self.borrows.len() {
             let left = self.borrows[read_idx - 1];
diff --git a/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs
new file mode 100644
index 00000000000..e62ee528686
--- /dev/null
+++ b/src/tools/miri/tests/pass/stacked-borrows/unknown-bottom-gc.rs
@@ -0,0 +1,21 @@
+//@compile-flags: -Zmiri-permissive-provenance
+#![feature(strict_provenance)]
+
+use std::ptr;
+
+fn main() {
+    let mut v = 1u8;
+    let ptr = &mut v as *mut u8;
+
+    // Expose the allocation and use the exposed pointer, creating an unknown bottom
+    unsafe {
+        let p: *mut u8 = ptr::from_exposed_addr::<u8>(ptr.expose_addr()) as *mut u8;
+        *p = 1;
+    }
+
+    // Pile on a lot of SharedReadOnly at the top of the stack
+    let r = &v;
+    for _ in 0..1024 {
+        let _x = &*r;
+    }
+}