Skip to content

Record allocation spans inside force_allocation #115184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion compiler/rustc_const_eval/src/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -471,6 +471,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
Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
};
Expand Down
18 changes: 18 additions & 0 deletions src/tools/miri/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
}
13 changes: 13 additions & 0 deletions src/tools/miri/tests/fail/dangling_pointers/dangling_primitive.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion src/tools/miri/tests/fail/dangling_pointers/dyn_size.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down