Skip to content

Commit eb4128f

Browse files
committed
don't call Stacked Borrows hooks at all when validation is disabled
1 parent c8450bd commit eb4128f

File tree

5 files changed

+62
-30
lines changed

5 files changed

+62
-30
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ Several `-Z` flags are relevant for Miri:
279279
* `-Zalways-encode-mir` makes rustc dump MIR even for completely monomorphic
280280
functions. This is needed so that Miri can execute such functions, so Miri
281281
sets this flag per default.
282+
* `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
283+
enables this per default because it is needed for validation.
282284

283285
Moreover, Miri recognizes some environment variables:
284286

src/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
3232
let mut ecx = InterpretCx::new(
3333
tcx.at(syntax::source_map::DUMMY_SP),
3434
ty::ParamEnv::reveal_all(),
35-
Evaluator::new(config.validate),
35+
Evaluator::new(),
3636
);
3737

3838
// FIXME: InterpretCx::new should take an initial MemoryExtra
39-
ecx.memory_mut().extra = MemoryExtra::with_rng(config.seed.map(StdRng::seed_from_u64));
39+
ecx.memory_mut().extra = MemoryExtra::new(config.seed.map(StdRng::seed_from_u64), config.validate);
4040

4141
let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
4242
let main_mir = ecx.load_mir(main_instance.def)?;

src/machine.rs

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,31 @@ impl Into<MemoryKind<MiriMemoryKind>> for MiriMemoryKind {
4141
/// Extra per-allocation data
4242
#[derive(Debug, Clone)]
4343
pub struct AllocExtra {
44-
pub stacked_borrows: stacked_borrows::AllocExtra,
44+
/// Stacked Borrows state is only added if validation is enabled.
45+
pub stacked_borrows: Option<stacked_borrows::AllocExtra>,
4546
}
4647

4748
/// Extra global memory data
4849
#[derive(Default, Clone, Debug)]
4950
pub struct MemoryExtra {
5051
pub stacked_borrows: stacked_borrows::MemoryExtra,
5152
pub intptrcast: intptrcast::MemoryExtra,
53+
5254
/// The random number generator to use if Miri is running in non-deterministic mode and to
5355
/// enable intptrcast
54-
pub(crate) rng: Option<RefCell<StdRng>>
56+
pub(crate) rng: Option<RefCell<StdRng>>,
57+
58+
/// Whether to enforce the validity invariant.
59+
pub(crate) validate: bool,
5560
}
5661

5762
impl MemoryExtra {
58-
pub fn with_rng(rng: Option<StdRng>) -> Self {
63+
pub fn new(rng: Option<StdRng>, validate: bool) -> Self {
5964
MemoryExtra {
6065
stacked_borrows: Default::default(),
6166
intptrcast: Default::default(),
6267
rng: rng.map(RefCell::new),
68+
validate,
6369
}
6470
}
6571
}
@@ -82,21 +88,17 @@ pub struct Evaluator<'tcx> {
8288

8389
/// TLS state.
8490
pub(crate) tls: TlsData<'tcx>,
85-
86-
/// Whether to enforce the validity invariant.
87-
pub(crate) validate: bool,
8891
}
8992

9093
impl<'tcx> Evaluator<'tcx> {
91-
pub(crate) fn new(validate: bool) -> Self {
94+
pub(crate) fn new() -> Self {
9295
Evaluator {
9396
env_vars: HashMap::default(),
9497
argc: None,
9598
argv: None,
9699
cmd_line: None,
97100
last_error: 0,
98101
tls: TlsData::default(),
99-
validate,
100102
}
101103
}
102104
}
@@ -135,7 +137,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
135137

136138
#[inline(always)]
137139
fn enforce_validity(ecx: &InterpretCx<'mir, 'tcx, Self>) -> bool {
138-
ecx.machine.validate
140+
ecx.memory().extra.validate
139141
}
140142

141143
/// Returns `Ok()` when the function was handled; fail otherwise.
@@ -251,12 +253,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
251253
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
252254
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
253255
let alloc = alloc.into_owned();
254-
let (stacks, base_tag) = Stacks::new_allocation(
255-
id,
256-
Size::from_bytes(alloc.bytes.len() as u64),
257-
Rc::clone(&memory.extra.stacked_borrows),
258-
kind,
259-
);
256+
let (stacks, base_tag) = if !memory.extra.validate {
257+
(None, Tag::Untagged)
258+
} else {
259+
let (stacks, base_tag) = Stacks::new_allocation(
260+
id,
261+
Size::from_bytes(alloc.bytes.len() as u64),
262+
Rc::clone(&memory.extra.stacked_borrows),
263+
kind,
264+
);
265+
(Some(stacks), base_tag)
266+
};
260267
if kind != MiriMemoryKind::Static.into() {
261268
assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
262269
// Now we can rely on the inner pointers being static, too.
@@ -268,7 +275,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
268275
alloc.relocations.iter()
269276
// The allocations in the relocations (pointers stored *inside* this allocation)
270277
// all get the base pointer tag.
271-
.map(|&(offset, ((), alloc))| (offset, (memory_extra.static_base_ptr(alloc), alloc)))
278+
.map(|&(offset, ((), alloc))| {
279+
let tag = if !memory.extra.validate {
280+
Tag::Untagged
281+
} else {
282+
memory_extra.static_base_ptr(alloc)
283+
};
284+
(offset, (tag, alloc))
285+
})
272286
.collect()
273287
),
274288
undef_mask: alloc.undef_mask,
@@ -286,7 +300,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
286300
id: AllocId,
287301
memory: &Memory<'mir, 'tcx, Self>,
288302
) -> Self::PointerTag {
289-
memory.extra.stacked_borrows.borrow_mut().static_base_ptr(id)
303+
if !memory.extra.validate {
304+
Tag::Untagged
305+
} else {
306+
memory.extra.stacked_borrows.borrow_mut().static_base_ptr(id)
307+
}
290308
}
291309

292310
#[inline(always)]
@@ -295,12 +313,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
295313
kind: mir::RetagKind,
296314
place: PlaceTy<'tcx, Tag>,
297315
) -> InterpResult<'tcx> {
298-
if !ecx.tcx.sess.opts.debugging_opts.mir_emit_retag || !Self::enforce_validity(ecx) {
299-
// No tracking, or no retagging. The latter is possible because a dependency of ours
300-
// might be called with different flags than we are, so there are `Retag`
301-
// statements but we do not want to execute them.
302-
// Also, honor the whitelist in `enforce_validity` because otherwise we might retag
303-
// uninitialized data.
316+
if !Self::enforce_validity(ecx) {
317+
// No tracking.
304318
Ok(())
305319
} else {
306320
ecx.retag(kind, place)
@@ -354,7 +368,11 @@ impl AllocationExtra<Tag> for AllocExtra {
354368
ptr: Pointer<Tag>,
355369
size: Size,
356370
) -> InterpResult<'tcx> {
357-
alloc.extra.stacked_borrows.memory_read(ptr, size)
371+
if let Some(ref stacked_borrows) = alloc.extra.stacked_borrows {
372+
stacked_borrows.memory_read(ptr, size)
373+
} else {
374+
Ok(())
375+
}
358376
}
359377

360378
#[inline(always)]
@@ -363,7 +381,11 @@ impl AllocationExtra<Tag> for AllocExtra {
363381
ptr: Pointer<Tag>,
364382
size: Size,
365383
) -> InterpResult<'tcx> {
366-
alloc.extra.stacked_borrows.memory_written(ptr, size)
384+
if let Some(ref mut stacked_borrows) = alloc.extra.stacked_borrows {
385+
stacked_borrows.memory_written(ptr, size)
386+
} else {
387+
Ok(())
388+
}
367389
}
368390

369391
#[inline(always)]
@@ -372,7 +394,11 @@ impl AllocationExtra<Tag> for AllocExtra {
372394
ptr: Pointer<Tag>,
373395
size: Size,
374396
) -> InterpResult<'tcx> {
375-
alloc.extra.stacked_borrows.memory_deallocated(ptr, size)
397+
if let Some(ref mut stacked_borrows) = alloc.extra.stacked_borrows {
398+
stacked_borrows.memory_deallocated(ptr, size)
399+
} else {
400+
Ok(())
401+
}
376402
}
377403
}
378404

src/stacked_borrows.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
538538

539539
// Get the allocation. It might not be mutable, so we cannot use `get_mut`.
540540
let alloc = this.memory().get(ptr.alloc_id)?;
541+
let stacked_borrows = alloc.extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data");
541542
// Update the stacks.
542543
// Make sure that raw pointers and mutable shared references are reborrowed "weak":
543544
// There could be existing unique pointers reborrowed from them that should remain valid!
@@ -553,14 +554,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
553554
// We are only ever `SharedReadOnly` inside the frozen bits.
554555
let perm = if frozen { Permission::SharedReadOnly } else { Permission::SharedReadWrite };
555556
let item = Item { perm, tag: new_tag, protector };
556-
alloc.extra.stacked_borrows.for_each(cur_ptr, size, |stack, global| {
557+
stacked_borrows.for_each(cur_ptr, size, |stack, global| {
557558
stack.grant(cur_ptr.tag, item, global)
558559
})
559560
});
560561
}
561562
};
562563
let item = Item { perm, tag: new_tag, protector };
563-
alloc.extra.stacked_borrows.for_each(ptr, size, |stack, global| {
564+
stacked_borrows.for_each(ptr, size, |stack, global| {
564565
stack.grant(ptr.tag, item, global)
565566
})
566567
}

tests/run-pass/transmute_fat.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Validation disallows this becuase the reference is never cast to a raw pointer.
2+
// compile-flags: -Zmiri-disable-validation
3+
14
fn main() {
25
// If we are careful, we can exploit data layout...
36
let raw = unsafe {

0 commit comments

Comments
 (0)