about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-25 17:03:33 +0000
committerbors <bors@rust-lang.org>2023-08-25 17:03:33 +0000
commit296c7a683cb7faafea3dd6905860cdeeae13598e (patch)
tree371ed0e225dcf8ea32e4fd7e56ea6520909f33f1
parenta8b905cd78c4ddfa4a7a517ada260506af4adfad (diff)
parent8ecdefb3db7e854561fd382ba19675c894f40170 (diff)
downloadrust-296c7a683cb7faafea3dd6905860cdeeae13598e.tar.gz
rust-296c7a683cb7faafea3dd6905860cdeeae13598e.zip
Auto merge of #115184 - saethlin:local-allocated-spans, r=RalfJung
Record allocation spans inside force_allocation

This expands https://github.com/rust-lang/miri/pull/2940 to cover locals

r? `@RalfJung`
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs14
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs9
-rw-r--r--src/tools/miri/src/machine.rs18
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs13
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr26
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr7
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr7
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr12
-rw-r--r--src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr7
-rw-r--r--src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr7
10 files changed, 110 insertions, 10 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 6be2e406917..91c07d73fce 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
 
 use super::{
     AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx,
-    InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
+    InterpResult, MPlaceTy, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -475,6 +475,18 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         assert!(!unwinding);
         Ok(StackPopJump::Normal)
     }
+
+    /// Called immediately after actual memory was allocated for a local
+    /// but before the local's stack frame is updated to point to that memory.
+    #[inline(always)]
+    fn after_local_allocated(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _frame: usize,
+        _local: mir::Local,
+        _mplace: &MPlaceTy<'tcx, Self::Provenance>,
+    ) -> InterpResult<'tcx> {
+        Ok(())
+    }
 }
 
 /// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index daadb758964..40a7a0f4e56 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -899,7 +899,7 @@ where
                         if local_layout.is_unsized() {
                             throw_unsup_format!("unsized locals are not supported");
                         }
-                        let mplace = *self.allocate(local_layout, MemoryKind::Stack)?;
+                        let mplace = self.allocate(local_layout, MemoryKind::Stack)?;
                         // Preserve old value. (As an optimization, we can skip this if it was uninit.)
                         if !matches!(local_val, Immediate::Uninit) {
                             // We don't have to validate as we can assume the local was already
@@ -909,15 +909,16 @@ where
                                 local_val,
                                 local_layout,
                                 local_layout.align.abi,
-                                mplace,
+                                *mplace,
                             )?;
                         }
+                        M::after_local_allocated(self, frame, local, &mplace)?;
                         // Now we can call `access_mut` again, asserting it goes well, and actually
                         // overwrite things. This points to the entire allocation, not just the part
                         // the place refers to, i.e. we do this before we apply `offset`.
                         *M::access_local_mut(self, frame, local).unwrap() =
-                            Operand::Indirect(mplace);
-                        mplace
+                            Operand::Indirect(*mplace);
+                        *mplace
                     }
                     &mut Operand::Indirect(mplace) => mplace, // this already was an indirect local
                 };
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 17cfcbb2018..98f82ec9a0f 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -1405,4 +1405,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         }
         res
     }
+
+    fn after_local_allocated(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        frame: usize,
+        local: mir::Local,
+        mplace: &MPlaceTy<'tcx, Provenance>
+    ) -> InterpResult<'tcx> {
+        let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else {
+            panic!("after_local_allocated should only be called on fresh allocations");
+        };
+        let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local];
+        let span = local_decl.source_info.span;
+        ecx.machine
+            .allocation_spans
+            .borrow_mut()
+            .insert(alloc_id, (span, None));
+        Ok(())
+    }
 }
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs
new file mode 100644
index 00000000000..393127341ca
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs
@@ -0,0 +1,13 @@
+// The interpreter tries to delay allocating locals until their address is taken.
+// This test checks that we correctly use the span associated with the local itself, not the span
+// where we take the address of the local and force it to be allocated.
+
+fn main() {
+    let ptr = {
+        let x = 0usize; // This line should appear in the helps
+        &x as *const usize // This line should NOT appear in the helps
+    };
+    unsafe {
+        dbg!(*ptr); //~ ERROR: has been freed
+    }
+}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr
new file mode 100644
index 00000000000..bdc9c31db40
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.stderr
@@ -0,0 +1,26 @@
+error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
+  --> $DIR/dangling_primitive.rs:LL:CC
+   |
+LL |         dbg!(*ptr);
+   |         ^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+help: ALLOC was allocated here:
+  --> $DIR/dangling_primitive.rs:LL:CC
+   |
+LL |         let x = 0usize; // This line should appear in the helps
+   |             ^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_primitive.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
+   = note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr
index fe039ef3ada..92b1fcb1145 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr
@@ -6,7 +6,12 @@ LL |     let val = unsafe { (*xptr).1 };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/deref-partially-dangling.rs:LL:CC
+   |
+LL |     let x = (1, 13);
+   |         ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/deref-partially-dangling.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
index 33aa6c84410..95a50bc8750 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
@@ -6,7 +6,12 @@ LL |     let _ptr = unsafe { &*ptr };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dyn_size.rs:LL:CC
+   |
+LL |     let buf = [0u32; 1];
+   |         ^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dyn_size.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr
index 500f28a3cbc..4d2dfe28aed 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr
@@ -6,7 +6,17 @@ LL |         let val = *x;
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/stack_temporary.rs:LL:CC
+   |
+LL |         let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"!
+   |                               ^
+help: ALLOC was deallocated here:
+  --> $DIR/stack_temporary.rs:LL:CC
+   |
+LL |         let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"!
+   |                                 ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/stack_temporary.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
index 4422310870a..e1102a6d216 100644
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr
@@ -6,7 +6,12 @@ LL |     let x = unsafe { x.offset(5) };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/out_of_bounds_ptr_1.rs:LL:CC
+   |
+LL |     let v = [0i8; 4];
+   |         ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/out_of_bounds_ptr_1.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
index 1364e0f9009..99f28b3e4f8 100644
--- a/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr
@@ -6,7 +6,12 @@ LL |     let x = unsafe { x.offset(-1) };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/out_of_bounds_ptr_3.rs:LL:CC
+   |
+LL |     let v = [0i8; 4];
+   |         ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/out_of_bounds_ptr_3.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace