diff options
| author | bors <bors@rust-lang.org> | 2023-08-25 17:03:33 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-08-25 17:03:33 +0000 |
| commit | 296c7a683cb7faafea3dd6905860cdeeae13598e (patch) | |
| tree | 371ed0e225dcf8ea32e4fd7e56ea6520909f33f1 | |
| parent | a8b905cd78c4ddfa4a7a517ada260506af4adfad (diff) | |
| parent | 8ecdefb3db7e854561fd382ba19675c894f40170 (diff) | |
| download | rust-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`
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 |
