Skip to content

Commit 296c7a6

Browse files
committed
Auto merge of rust-lang#115184 - saethlin:local-allocated-spans, r=RalfJung
Record allocation spans inside force_allocation This expands rust-lang/miri#2940 to cover locals r? `@RalfJung`
2 parents a8b905c + 8ecdefb commit 296c7a6

File tree

10 files changed

+110
-10
lines changed

10 files changed

+110
-10
lines changed

compiler/rustc_const_eval/src/interpret/machine.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
1818

1919
use super::{
2020
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx,
21-
InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
21+
InterpResult, MPlaceTy, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
2222
};
2323

2424
/// Data returned by Machine::stack_pop,
@@ -475,6 +475,18 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
475475
assert!(!unwinding);
476476
Ok(StackPopJump::Normal)
477477
}
478+
479+
/// Called immediately after actual memory was allocated for a local
480+
/// but before the local's stack frame is updated to point to that memory.
481+
#[inline(always)]
482+
fn after_local_allocated(
483+
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
484+
_frame: usize,
485+
_local: mir::Local,
486+
_mplace: &MPlaceTy<'tcx, Self::Provenance>,
487+
) -> InterpResult<'tcx> {
488+
Ok(())
489+
}
478490
}
479491

480492
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines

compiler/rustc_const_eval/src/interpret/place.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ where
899899
if local_layout.is_unsized() {
900900
throw_unsup_format!("unsized locals are not supported");
901901
}
902-
let mplace = *self.allocate(local_layout, MemoryKind::Stack)?;
902+
let mplace = self.allocate(local_layout, MemoryKind::Stack)?;
903903
// Preserve old value. (As an optimization, we can skip this if it was uninit.)
904904
if !matches!(local_val, Immediate::Uninit) {
905905
// We don't have to validate as we can assume the local was already
@@ -909,15 +909,16 @@ where
909909
local_val,
910910
local_layout,
911911
local_layout.align.abi,
912-
mplace,
912+
*mplace,
913913
)?;
914914
}
915+
M::after_local_allocated(self, frame, local, &mplace)?;
915916
// Now we can call `access_mut` again, asserting it goes well, and actually
916917
// overwrite things. This points to the entire allocation, not just the part
917918
// the place refers to, i.e. we do this before we apply `offset`.
918919
*M::access_local_mut(self, frame, local).unwrap() =
919-
Operand::Indirect(mplace);
920-
mplace
920+
Operand::Indirect(*mplace);
921+
*mplace
921922
}
922923
&mut Operand::Indirect(mplace) => mplace, // this already was an indirect local
923924
};

src/tools/miri/src/machine.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1405,4 +1405,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
14051405
}
14061406
res
14071407
}
1408+
1409+
fn after_local_allocated(
1410+
ecx: &mut InterpCx<'mir, 'tcx, Self>,
1411+
frame: usize,
1412+
local: mir::Local,
1413+
mplace: &MPlaceTy<'tcx, Provenance>
1414+
) -> InterpResult<'tcx> {
1415+
let Some(Provenance::Concrete { alloc_id, .. }) = mplace.ptr.provenance else {
1416+
panic!("after_local_allocated should only be called on fresh allocations");
1417+
};
1418+
let local_decl = &ecx.active_thread_stack()[frame].body.local_decls[local];
1419+
let span = local_decl.source_info.span;
1420+
ecx.machine
1421+
.allocation_spans
1422+
.borrow_mut()
1423+
.insert(alloc_id, (span, None));
1424+
Ok(())
1425+
}
14081426
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// The interpreter tries to delay allocating locals until their address is taken.
2+
// This test checks that we correctly use the span associated with the local itself, not the span
3+
// where we take the address of the local and force it to be allocated.
4+
5+
fn main() {
6+
let ptr = {
7+
let x = 0usize; // This line should appear in the helps
8+
&x as *const usize // This line should NOT appear in the helps
9+
};
10+
unsafe {
11+
dbg!(*ptr); //~ ERROR: has been freed
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: Undefined Behavior: dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
2+
--> $DIR/dangling_primitive.rs:LL:CC
3+
|
4+
LL | dbg!(*ptr);
5+
| ^^^^^^^^^^ dereferencing pointer failed: ALLOC has been freed, so this pointer is dangling
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
help: ALLOC was allocated here:
10+
--> $DIR/dangling_primitive.rs:LL:CC
11+
|
12+
LL | let x = 0usize; // This line should appear in the helps
13+
| ^
14+
help: ALLOC was deallocated here:
15+
--> $DIR/dangling_primitive.rs:LL:CC
16+
|
17+
LL | };
18+
| ^
19+
= note: BACKTRACE (of the first span):
20+
= note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC
21+
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
22+
23+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
24+
25+
error: aborting due to previous error
26+

src/tools/miri/tests/fail/dangling_pointers/deref-partially-dangling.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ LL | let val = unsafe { (*xptr).1 };
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
9+
help: ALLOC was allocated here:
10+
--> $DIR/deref-partially-dangling.rs:LL:CC
11+
|
12+
LL | let x = (1, 13);
13+
| ^
14+
= note: BACKTRACE (of the first span):
1015
= note: inside `main` at $DIR/deref-partially-dangling.rs:LL:CC
1116

1217
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ LL | let _ptr = unsafe { &*ptr };
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
9+
help: ALLOC was allocated here:
10+
--> $DIR/dyn_size.rs:LL:CC
11+
|
12+
LL | let buf = [0u32; 1];
13+
| ^^^
14+
= note: BACKTRACE (of the first span):
1015
= note: inside `main` at $DIR/dyn_size.rs:LL:CC
1116

1217
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

src/tools/miri/tests/fail/dangling_pointers/stack_temporary.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,17 @@ LL | let val = *x;
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
9+
help: ALLOC was allocated here:
10+
--> $DIR/stack_temporary.rs:LL:CC
11+
|
12+
LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"!
13+
| ^
14+
help: ALLOC was deallocated here:
15+
--> $DIR/stack_temporary.rs:LL:CC
16+
|
17+
LL | let x = make_ref(&mut 0); // The temporary storing "0" is deallocated at the ";"!
18+
| ^
19+
= note: BACKTRACE (of the first span):
1020
= note: inside `main` at $DIR/stack_temporary.rs:LL:CC
1121

1222
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_1.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ LL | let x = unsafe { x.offset(5) };
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
9+
help: ALLOC was allocated here:
10+
--> $DIR/out_of_bounds_ptr_1.rs:LL:CC
11+
|
12+
LL | let v = [0i8; 4];
13+
| ^
14+
= note: BACKTRACE (of the first span):
1015
= note: inside `main` at $DIR/out_of_bounds_ptr_1.rs:LL:CC
1116

1217
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

src/tools/miri/tests/fail/intrinsics/out_of_bounds_ptr_3.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ LL | let x = unsafe { x.offset(-1) };
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9-
= note: BACKTRACE:
9+
help: ALLOC was allocated here:
10+
--> $DIR/out_of_bounds_ptr_3.rs:LL:CC
11+
|
12+
LL | let v = [0i8; 4];
13+
| ^
14+
= note: BACKTRACE (of the first span):
1015
= note: inside `main` at $DIR/out_of_bounds_ptr_3.rs:LL:CC
1116

1217
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

0 commit comments

Comments
 (0)