Record allocation spans inside force_allocation
This commit is contained in:
parent
18be2728bd
commit
ec21d584ee
10 changed files with 107 additions and 10 deletions
|
@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx,
|
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,
|
/// Data returned by Machine::stack_pop,
|
||||||
|
@ -471,6 +471,15 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||||
assert!(!unwinding);
|
assert!(!unwinding);
|
||||||
Ok(StackPopJump::Normal)
|
Ok(StackPopJump::Normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
/// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines
|
||||||
|
|
|
@ -899,7 +899,7 @@ where
|
||||||
if local_layout.is_unsized() {
|
if local_layout.is_unsized() {
|
||||||
throw_unsup_format!("unsized locals are not supported");
|
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.)
|
// Preserve old value. (As an optimization, we can skip this if it was uninit.)
|
||||||
if !matches!(local_val, Immediate::Uninit) {
|
if !matches!(local_val, Immediate::Uninit) {
|
||||||
// We don't have to validate as we can assume the local was already
|
// We don't have to validate as we can assume the local was already
|
||||||
|
@ -909,15 +909,16 @@ where
|
||||||
local_val,
|
local_val,
|
||||||
local_layout,
|
local_layout,
|
||||||
local_layout.align.abi,
|
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
|
// 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
|
// 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`.
|
// the place refers to, i.e. we do this before we apply `offset`.
|
||||||
*M::access_local_mut(self, frame, local).unwrap() =
|
*M::access_local_mut(self, frame, local).unwrap() =
|
||||||
Operand::Indirect(mplace);
|
Operand::Indirect(*mplace);
|
||||||
mplace
|
*mplace
|
||||||
}
|
}
|
||||||
&mut Operand::Indirect(mplace) => mplace, // this already was an indirect local
|
&mut Operand::Indirect(mplace) => mplace, // this already was an indirect local
|
||||||
};
|
};
|
||||||
|
|
|
@ -1405,4 +1405,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
||||||
}
|
}
|
||||||
res
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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: 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: 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: 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
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
|
@ -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: 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: 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: inside `main` at $DIR/dyn_size.rs:LL:CC
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
|
@ -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: 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: 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: inside `main` at $DIR/stack_temporary.rs:LL:CC
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
|
@ -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: 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: 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: 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
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
|
@ -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: 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: 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: 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
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue