Skip to content

Commit 1944513

Browse files
committed
add an option to track raw pointer tags in Stacked Borrows
1 parent 39f7b35 commit 1944513

File tree

5 files changed

+43
-39
lines changed

5 files changed

+43
-39
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,17 @@ environment variable:
232232
* `-Zmiri-track-alloc-id=<id>` shows a backtrace when the given allocation is
233233
being allocated or freed. This helps in debugging memory leaks and
234234
use after free bugs.
235+
* `-Zmiri-track-call-id=<id>` shows a backtrace when the given call id is
236+
assigned to a stack frame. This helps in debugging UB related to Stacked
237+
Borrows "protectors".
235238
* `-Zmiri-track-pointer-tag=<tag>` shows a backtrace when the given pointer tag
236239
is popped from a borrow stack (which is where the tag becomes invalid and any
237240
future use of it will error). This helps you in finding out why UB is
238241
happening and where in your code would be a good place to look for it.
239-
* `-Zmiri-track-call-id=<id>` shows a backtrace when the given call id is
240-
assigned to a stack frame. This helps in debugging UB related to Stacked
241-
Borrows "protectors".
242+
* `-Zmiri-track-raw-pointers` makes Stacked Borrows track a pointer tag even for
243+
raw pointers. This can make valid code fail to pass the checks (when
244+
integer-pointer casts are involved), but also can help identify latent
245+
aliasing issues in code that Miri accepts by default.
242246

243247
Some native rustc `-Z` flags are also very relevant for Miri:
244248

src/bin/miri.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ fn main() {
207207
"-Zmiri-ignore-leaks" => {
208208
miri_config.ignore_leaks = true;
209209
}
210+
"-Zmiri-track-raw-pointers" => {
211+
miri_config.track_raw = true;
212+
}
210213
"--" => {
211214
after_dashdash = true;
212215
}

src/eval.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
use std::convert::TryFrom;
44
use std::ffi::OsStr;
55

6-
use rand::rngs::StdRng;
7-
use rand::SeedableRng;
86
use log::info;
97

108
use rustc_hir::def_id::DefId;
@@ -48,6 +46,8 @@ pub struct MiriConfig {
4846
pub tracked_call_id: Option<CallId>,
4947
/// The allocation id to report about.
5048
pub tracked_alloc_id: Option<AllocId>,
49+
/// Whether to track raw pointers in stacked borrows.
50+
pub track_raw: bool,
5151
}
5252

5353
impl Default for MiriConfig {
@@ -64,6 +64,7 @@ impl Default for MiriConfig {
6464
tracked_pointer_tag: None,
6565
tracked_call_id: None,
6666
tracked_alloc_id: None,
67+
track_raw: false,
6768
}
6869
}
6970
}
@@ -84,14 +85,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
8485
rustc_span::source_map::DUMMY_SP,
8586
param_env,
8687
Evaluator::new(config.communicate, config.validate, layout_cx),
87-
MemoryExtra::new(
88-
StdRng::seed_from_u64(config.seed.unwrap_or(0)),
89-
config.stacked_borrows,
90-
config.tracked_pointer_tag,
91-
config.tracked_call_id,
92-
config.tracked_alloc_id,
93-
config.check_alignment,
94-
),
88+
MemoryExtra::new(&config),
9589
);
9690
// Complete initialization.
9791
EnvVars::init(&mut ecx, config.excluded_env_vars)?;

src/machine.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::fmt;
1010

1111
use log::trace;
1212
use rand::rngs::StdRng;
13+
use rand::SeedableRng;
1314

1415
use rustc_data_structures::fx::FxHashMap;
1516
use rustc_middle::{
@@ -132,16 +133,14 @@ pub struct MemoryExtra {
132133
}
133134

134135
impl MemoryExtra {
135-
pub fn new(
136-
rng: StdRng,
137-
stacked_borrows: bool,
138-
tracked_pointer_tag: Option<PtrId>,
139-
tracked_call_id: Option<CallId>,
140-
tracked_alloc_id: Option<AllocId>,
141-
check_alignment: AlignmentCheck,
142-
) -> Self {
143-
let stacked_borrows = if stacked_borrows {
144-
Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(tracked_pointer_tag, tracked_call_id))))
136+
pub fn new(config: &MiriConfig) -> Self {
137+
let rng = StdRng::seed_from_u64(config.seed.unwrap_or(0));
138+
let stacked_borrows = if config.stacked_borrows {
139+
Some(Rc::new(RefCell::new(stacked_borrows::GlobalState::new(
140+
config.tracked_pointer_tag,
141+
config.tracked_call_id,
142+
config.track_raw,
143+
))))
145144
} else {
146145
None
147146
};
@@ -150,8 +149,8 @@ impl MemoryExtra {
150149
intptrcast: Default::default(),
151150
extern_statics: FxHashMap::default(),
152151
rng: RefCell::new(rng),
153-
tracked_alloc_id,
154-
check_alignment,
152+
tracked_alloc_id: config.tracked_alloc_id,
153+
check_alignment: config.check_alignment,
155154
}
156155
}
157156

src/stacked_borrows.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ pub struct GlobalState {
108108
tracked_pointer_tag: Option<PtrId>,
109109
/// The call id to trace
110110
tracked_call_id: Option<CallId>,
111+
/// Whether to track raw pointers.
112+
track_raw: bool,
111113
}
112114
/// Memory extra state gives us interior mutable access to the global state.
113115
pub type MemoryExtra = Rc<RefCell<GlobalState>>;
@@ -155,14 +157,15 @@ impl fmt::Display for RefKind {
155157

156158
/// Utilities for initialization and ID generation
157159
impl GlobalState {
158-
pub fn new(tracked_pointer_tag: Option<PtrId>, tracked_call_id: Option<CallId>) -> Self {
160+
pub fn new(tracked_pointer_tag: Option<PtrId>, tracked_call_id: Option<CallId>, track_raw: bool) -> Self {
159161
GlobalState {
160162
next_ptr_id: NonZeroU64::new(1).unwrap(),
161163
base_ptr_ids: FxHashMap::default(),
162164
next_call_id: NonZeroU64::new(1).unwrap(),
163165
active_calls: FxHashSet::default(),
164166
tracked_pointer_tag,
165167
tracked_call_id,
168+
track_raw,
166169
}
167170
}
168171

@@ -479,9 +482,12 @@ impl Stacks {
479482
// The base pointer is not unique, so the base permission is `SharedReadWrite`.
480483
MemoryKind::Machine(MiriMemoryKind::Global | MiriMemoryKind::ExternStatic | MiriMemoryKind::Tls | MiriMemoryKind::Env) =>
481484
(extra.borrow_mut().global_base_ptr(id), Permission::SharedReadWrite),
482-
// Everything else we handle entirely untagged for now.
483-
// FIXME: experiment with more precise tracking.
484-
_ => (Tag::Untagged, Permission::SharedReadWrite),
485+
// Everything else we handle like raw pointers for now.
486+
_ => {
487+
let mut extra = extra.borrow_mut();
488+
let tag = if extra.track_raw { Tag::Tagged(extra.new_ptr()) } else { Tag::Untagged };
489+
(tag, Permission::SharedReadWrite)
490+
}
485491
};
486492
(Stacks::new(size, perm, tag, extra), tag)
487493
}
@@ -593,16 +599,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
593599
}
594600

595601
// Compute new borrow.
596-
let new_tag = match kind {
597-
// Give up tracking for raw pointers.
598-
// FIXME: Experiment with more precise tracking. Blocked on `&raw`
599-
// because `Rc::into_raw` currently creates intermediate references,
600-
// breaking `Rc::from_raw`.
601-
RefKind::Raw { .. } => Tag::Untagged,
602-
// All other pointesr are properly tracked.
603-
_ => Tag::Tagged(
604-
this.memory.extra.stacked_borrows.as_ref().unwrap().borrow_mut().new_ptr(),
605-
),
602+
let new_tag = {
603+
let mut mem_extra = this.memory.extra.stacked_borrows.as_ref().unwrap().borrow_mut();
604+
match kind {
605+
// Give up tracking for raw pointers.
606+
RefKind::Raw { .. } if !mem_extra.track_raw => Tag::Untagged,
607+
// All other pointers are properly tracked.
608+
_ => Tag::Tagged(mem_extra.new_ptr()),
609+
}
606610
};
607611

608612
// Reborrow.

0 commit comments

Comments
 (0)