Add a scheme to find the place where an id was destroyed
This commit is contained in:
parent
048af40923
commit
d363a47fcb
8 changed files with 55 additions and 9 deletions
|
|
@ -32,6 +32,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls<'_> {
|
|||
excluded_env_vars: vec![],
|
||||
args: vec![],
|
||||
seed: None,
|
||||
tracked_id: None,
|
||||
};
|
||||
eval_main(tcx, entry_def_id, config);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
|
|||
excluded_env_vars: vec![],
|
||||
args: vec![],
|
||||
seed: None,
|
||||
tracked_id: None,
|
||||
};
|
||||
let did = self.0.hir().body_owner_def_id(body_id);
|
||||
println!("running test: {}", self.0.def_path_debug_str(did));
|
||||
|
|
@ -64,7 +65,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
|
|||
ignore_leaks: false,
|
||||
excluded_env_vars: vec![],
|
||||
args: vec![],
|
||||
seed: None
|
||||
seed: None,
|
||||
tracked_id: None,
|
||||
};
|
||||
miri::eval_main(tcx, entry_def_id, config);
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ fn main() {
|
|||
let mut communicate = false;
|
||||
let mut ignore_leaks = false;
|
||||
let mut seed: Option<u64> = None;
|
||||
let mut tracked_id: Option<miri::PtrId> = None;
|
||||
let mut rustc_args = vec![];
|
||||
let mut miri_args = vec![];
|
||||
let mut after_dashdash = false;
|
||||
|
|
@ -176,6 +177,17 @@ fn main() {
|
|||
arg if arg.starts_with("-Zmiri-env-exclude=") => {
|
||||
excluded_env_vars.push(arg.trim_start_matches("-Zmiri-env-exclude=").to_owned());
|
||||
},
|
||||
arg if arg.starts_with("-Zmiri-track-id=") => {
|
||||
let id: u64 = match arg.trim_start_matches("-Zmiri-track-id=").parse() {
|
||||
Ok(id) => id,
|
||||
Err(err) => panic!("-Zmiri-track-id requires a valid `u64` as the argument: {}", err),
|
||||
};
|
||||
if let Some(id) = miri::PtrId::new(id) {
|
||||
tracked_id = Some(id);
|
||||
} else {
|
||||
panic!("-Zmiri-track-id must be a nonzero id");
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
rustc_args.push(arg);
|
||||
}
|
||||
|
|
@ -208,6 +220,7 @@ fn main() {
|
|||
excluded_env_vars,
|
||||
seed,
|
||||
args: miri_args,
|
||||
tracked_id,
|
||||
};
|
||||
rustc_driver::install_ice_hook();
|
||||
let result = rustc_driver::catch_fatal_errors(move || {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ pub struct MiriConfig {
|
|||
pub args: Vec<String>,
|
||||
/// The seed to use when non-determinism or randomness are required (e.g. ptr-to-int cast, `getrandom()`).
|
||||
pub seed: Option<u64>,
|
||||
/// The stacked borrow id to report about
|
||||
pub tracked_id: Option<PtrId>,
|
||||
}
|
||||
|
||||
/// Details of premature program termination.
|
||||
|
|
@ -47,7 +49,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
|||
tcx.at(syntax::source_map::DUMMY_SP),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
Evaluator::new(config.communicate),
|
||||
MemoryExtra::new(StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.validate),
|
||||
MemoryExtra::new(StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.validate, config.tracked_id),
|
||||
);
|
||||
// Complete initialization.
|
||||
EnvVars::init(&mut ecx, config.excluded_env_vars);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
|
|||
pub use crate::range_map::RangeMap;
|
||||
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
|
||||
pub use crate::mono_hash_map::MonoHashMap;
|
||||
pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item};
|
||||
pub use crate::stacked_borrows::{
|
||||
EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item, PtrId,
|
||||
GlobalState,
|
||||
};
|
||||
pub use crate::machine::{
|
||||
PAGE_SIZE, STACK_ADDR, STACK_SIZE, NUM_CPUS,
|
||||
MemoryExtra, AllocExtra, FrameData, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt,
|
||||
|
|
|
|||
|
|
@ -77,9 +77,9 @@ pub struct MemoryExtra {
|
|||
}
|
||||
|
||||
impl MemoryExtra {
|
||||
pub fn new(rng: StdRng, validate: bool) -> Self {
|
||||
pub fn new(rng: StdRng, validate: bool, tracked_id: Option<PtrId>) -> Self {
|
||||
MemoryExtra {
|
||||
stacked_borrows: Default::default(),
|
||||
stacked_borrows: Rc::new(RefCell::new(GlobalState::new(tracked_id))),
|
||||
intptrcast: Default::default(),
|
||||
rng: RefCell::new(rng),
|
||||
validate,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ pub struct GlobalState {
|
|||
next_call_id: CallId,
|
||||
/// Those call IDs corresponding to functions that are still running.
|
||||
active_calls: HashSet<CallId>,
|
||||
/// The id to trace in this execution run
|
||||
tracked_id: Option<PtrId>,
|
||||
}
|
||||
/// Memory extra state gives us interior mutable access to the global state.
|
||||
pub type MemoryExtra = Rc<RefCell<GlobalState>>;
|
||||
|
|
@ -151,18 +153,17 @@ impl fmt::Display for RefKind {
|
|||
}
|
||||
|
||||
/// Utilities for initialization and ID generation
|
||||
impl Default for GlobalState {
|
||||
fn default() -> Self {
|
||||
impl GlobalState {
|
||||
pub fn new(tracked_id: Option<PtrId>) -> Self {
|
||||
GlobalState {
|
||||
next_ptr_id: NonZeroU64::new(1).unwrap(),
|
||||
base_ptr_ids: HashMap::default(),
|
||||
next_call_id: NonZeroU64::new(1).unwrap(),
|
||||
active_calls: HashSet::default(),
|
||||
tracked_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GlobalState {
|
||||
fn new_ptr(&mut self) -> PtrId {
|
||||
let id = self.next_ptr_id;
|
||||
self.next_ptr_id = NonZeroU64::new(id.get() + 1).unwrap();
|
||||
|
|
@ -312,6 +313,11 @@ impl<'tcx> Stack {
|
|||
let first_incompatible_idx = self.find_first_write_incompatible(granting_idx);
|
||||
for item in self.borrows.drain(first_incompatible_idx..).rev() {
|
||||
trace!("access: popping item {:?}", item);
|
||||
if let Tag::Tagged(id) = item.tag {
|
||||
if Some(id) == global.tracked_id {
|
||||
throw_unsup!(Unsupported(format!("popped id {}", id)));
|
||||
}
|
||||
}
|
||||
Stack::check_protector(&item, Some(tag), global)?;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
19
tests/compile-fail/stacked_borrows/track_id.rs
Normal file
19
tests/compile-fail/stacked_borrows/track_id.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// compile-flags: -Zmiri-track-id=1372
|
||||
// do not run on anything but x86_64 linux, because minute changes can change the borrow stack ids
|
||||
// only-x86_64
|
||||
// only-linux
|
||||
|
||||
use std::mem;
|
||||
|
||||
fn main() {
|
||||
let mut target = 42;
|
||||
// Make sure we cannot use a raw-tagged `&mut` pointing to a frozen location.
|
||||
// Even just creating it unfreezes.
|
||||
let raw = &mut target as *mut _; // let this leak to raw
|
||||
let reference = unsafe { &*raw }; // freeze
|
||||
let ptr = reference as *const _ as *mut i32; // raw ptr, with raw tag
|
||||
let _mut_ref: &mut i32 = unsafe { mem::transmute(ptr) }; // &mut, with raw tag
|
||||
//~^ ERROR popped id 1372
|
||||
// Now we retag, making our ref top-of-stack -- and, in particular, unfreezing.
|
||||
let _val = *reference;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue