Skip to content

Commit 3b4402c

Browse files
committed
Auto merge of rust-lang#2196 - carbotaniuman:permissive-stacked-borrows, r=RalfJung
Handle wildcard pointers in SB This uses an permissive `Unknown` implementation, where a wildcard pointer (and any SRW derived from a wildcard pointer) can access any previously-exposed SB tag. This is missing any meaningful test-cases, and all of the edge-cases have not yet been worked through. I think there's also some bugs here with differing Unknowns in different ranges and having things behave really weirdly too, alongside some issues with retagging to `SRO` or `Unique`.
2 parents a1226c4 + 58c79c5 commit 3b4402c

19 files changed

+555
-163
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,9 +358,7 @@ to Miri failing to detect cases of undefined behavior in a program.
358358
for pointer-to-int and int-to-pointer casts, respectively. This will
359359
necessarily miss some bugs as those semantics are not efficiently
360360
implementable in a sanitizer, but it will only miss bugs that concerns
361-
memory/pointers which is subject to these operations. Also note that this flag
362-
is currently incompatible with Stacked Borrows, so you will have to also pass
363-
`-Zmiri-disable-stacked-borrows` to use this.
361+
memory/pointers which is subject to these operations.
364362
* `-Zmiri-symbolic-alignment-check` makes the alignment check more strict. By
365363
default, alignment is checked by casting the pointer to an integer, and making
366364
sure that is a multiple of the alignment. This can lead to cases where a

src/diagnostics.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::ty;
88
use rustc_span::{source_map::DUMMY_SP, Span, SpanData, Symbol};
99

1010
use crate::helpers::HexRange;
11-
use crate::stacked_borrows::{diagnostics::TagHistory, AccessKind, SbTag};
11+
use crate::stacked_borrows::{diagnostics::TagHistory, AccessKind};
1212
use crate::*;
1313

1414
/// Details of premature program termination.
@@ -61,9 +61,9 @@ impl MachineStopType for TerminationInfo {}
6161
/// Miri specific diagnostics
6262
pub enum NonHaltingDiagnostic {
6363
CreatedPointerTag(NonZeroU64),
64-
/// This `Item` was popped from the borrow stack, either due to a grant of
65-
/// `AccessKind` to `SbTag` or a deallocation when the second argument is `None`.
66-
PoppedPointerTag(Item, Option<(SbTag, AccessKind)>),
64+
/// This `Item` was popped from the borrow stack, either due to an access with the given tag or
65+
/// a deallocation when the second argument is `None`.
66+
PoppedPointerTag(Item, Option<(SbTagExtra, AccessKind)>),
6767
CreatedCallId(CallId),
6868
CreatedAlloc(AllocId),
6969
FreedAlloc(AllocId),

src/intptrcast.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,16 @@ impl<'mir, 'tcx> GlobalStateInner {
101101
}
102102
}
103103

104-
pub fn expose_addr(ecx: &MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId) {
105-
trace!("Exposing allocation id {:?}", alloc_id);
106-
107-
let mut global_state = ecx.machine.intptrcast.borrow_mut();
104+
pub fn expose_ptr(ecx: &mut MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId, sb: SbTag) {
105+
let global_state = ecx.machine.intptrcast.get_mut();
108106
// In legacy and strict mode, we don't need this, so we can save some cycles
109107
// by not tracking it.
110108
if global_state.provenance_mode == ProvenanceMode::Permissive {
109+
trace!("Exposing allocation id {alloc_id:?}");
111110
global_state.exposed.insert(alloc_id);
111+
if ecx.machine.stacked_borrows.is_some() {
112+
ecx.expose_tag(alloc_id, sb);
113+
}
112114
}
113115
}
114116

@@ -140,9 +142,7 @@ impl<'mir, 'tcx> GlobalStateInner {
140142
// Determine the allocation this points to at cast time.
141143
let alloc_id = Self::alloc_id_from_addr(ecx, addr);
142144
Pointer::new(
143-
alloc_id.map(|alloc_id| {
144-
Tag::Concrete(ConcreteTag { alloc_id, sb: SbTag::Untagged })
145-
}),
145+
alloc_id.map(|alloc_id| Tag::Concrete { alloc_id, sb: SbTag::Untagged }),
146146
Size::from_bytes(addr),
147147
)
148148
}
@@ -220,8 +220,8 @@ impl<'mir, 'tcx> GlobalStateInner {
220220
) -> Option<(AllocId, Size)> {
221221
let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
222222

223-
let alloc_id = if let Tag::Concrete(concrete) = tag {
224-
concrete.alloc_id
223+
let alloc_id = if let Tag::Concrete { alloc_id, .. } = tag {
224+
alloc_id
225225
} else {
226226
// A wildcard pointer.
227227
assert_eq!(ecx.machine.intptrcast.borrow().provenance_mode, ProvenanceMode::Permissive);

src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#![feature(let_else)]
77
#![feature(io_error_more)]
88
#![feature(yeet_expr)]
9+
#![feature(is_some_with)]
10+
#![feature(nonzero_ops)]
911
#![warn(rust_2018_idioms)]
1012
#![allow(
1113
clippy::collapsible_else_if,
@@ -80,15 +82,15 @@ pub use crate::eval::{
8082
pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
8183
pub use crate::intptrcast::ProvenanceMode;
8284
pub use crate::machine::{
83-
AllocExtra, ConcreteTag, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt,
84-
MiriMemoryKind, Tag, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
85+
AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, Tag,
86+
NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
8587
};
8688
pub use crate::mono_hash_map::MonoHashMap;
8789
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
8890
pub use crate::range_map::RangeMap;
8991
pub use crate::stacked_borrows::{
90-
CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, PtrId, SbTag, Stack,
91-
Stacks,
92+
CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, PtrId, SbTag, SbTagExtra,
93+
Stack, Stacks,
9294
};
9395
pub use crate::sync::{CondvarId, EvalContextExt as SyncEvalContextExt, MutexId, RwLockId};
9496
pub use crate::thread::{

src/machine.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,14 @@ impl fmt::Display for MiriMemoryKind {
130130
/// Pointer provenance (tag).
131131
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
132132
pub enum Tag {
133-
Concrete(ConcreteTag),
133+
Concrete {
134+
alloc_id: AllocId,
135+
/// Stacked Borrows tag.
136+
sb: SbTag,
137+
},
134138
Wildcard,
135139
}
136140

137-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
138-
pub struct ConcreteTag {
139-
pub alloc_id: AllocId,
140-
/// Stacked Borrows tag.
141-
pub sb: SbTag,
142-
}
143-
144141
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
145142
static_assert_size!(Pointer<Tag>, 24);
146143
// #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@@ -160,15 +157,15 @@ impl Provenance for Tag {
160157
write!(f, "0x{:x}", addr.bytes())?;
161158

162159
match tag {
163-
Tag::Concrete(tag) => {
160+
Tag::Concrete { alloc_id, sb } => {
164161
// Forward `alternate` flag to `alloc_id` printing.
165162
if f.alternate() {
166-
write!(f, "[{:#?}]", tag.alloc_id)?;
163+
write!(f, "[{:#?}]", alloc_id)?;
167164
} else {
168-
write!(f, "[{:?}]", tag.alloc_id)?;
165+
write!(f, "[{:?}]", alloc_id)?;
169166
}
170167
// Print Stacked Borrows tag.
171-
write!(f, "{:?}", tag.sb)?;
168+
write!(f, "{:?}", sb)?;
172169
}
173170
Tag::Wildcard => {
174171
write!(f, "[Wildcard]")?;
@@ -180,7 +177,7 @@ impl Provenance for Tag {
180177

181178
fn get_alloc_id(self) -> Option<AllocId> {
182179
match self {
183-
Tag::Concrete(concrete) => Some(concrete.alloc_id),
180+
Tag::Concrete { alloc_id, .. } => Some(alloc_id),
184181
Tag::Wildcard => None,
185182
}
186183
}
@@ -489,7 +486,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
489486
type AllocExtra = AllocExtra;
490487

491488
type PointerTag = Tag;
492-
type TagExtra = SbTag;
489+
type TagExtra = SbTagExtra;
493490

494491
type MemoryMap =
495492
MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
@@ -649,7 +646,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
649646
let alloc: Allocation<Tag, Self::AllocExtra> = alloc.convert_tag_add_extra(
650647
&ecx.tcx,
651648
AllocExtra {
652-
stacked_borrows: stacks,
649+
stacked_borrows: stacks.map(RefCell::new),
653650
data_race: race_alloc,
654651
weak_memory: buffer_alloc,
655652
},
@@ -682,7 +679,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
682679
SbTag::Untagged
683680
};
684681
Pointer::new(
685-
Tag::Concrete(ConcreteTag { alloc_id: ptr.provenance, sb: sb_tag }),
682+
Tag::Concrete { alloc_id: ptr.provenance, sb: sb_tag },
686683
Size::from_bytes(absolute_addr),
687684
)
688685
}
@@ -708,8 +705,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
708705
ptr: Pointer<Self::PointerTag>,
709706
) -> InterpResult<'tcx> {
710707
match ptr.provenance {
711-
Tag::Concrete(concrete) =>
712-
intptrcast::GlobalStateInner::expose_addr(ecx, concrete.alloc_id),
708+
Tag::Concrete { alloc_id, sb } => {
709+
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, sb);
710+
}
713711
Tag::Wildcard => {
714712
// No need to do anything for wildcard pointers as
715713
// their provenances have already been previously exposed.
@@ -728,8 +726,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
728726

729727
rel.map(|(alloc_id, size)| {
730728
let sb = match ptr.provenance {
731-
Tag::Concrete(ConcreteTag { sb, .. }) => sb,
732-
Tag::Wildcard => SbTag::Untagged,
729+
Tag::Concrete { sb, .. } => SbTagExtra::Concrete(sb),
730+
Tag::Wildcard => SbTagExtra::Wildcard,
733731
};
734732
(alloc_id, size, sb)
735733
})
@@ -747,7 +745,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
747745
data_race.read(alloc_id, range, machine.data_race.as_ref().unwrap())?;
748746
}
749747
if let Some(stacked_borrows) = &alloc_extra.stacked_borrows {
750-
stacked_borrows.memory_read(
748+
stacked_borrows.borrow_mut().memory_read(
751749
alloc_id,
752750
tag,
753751
range,
@@ -773,7 +771,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
773771
data_race.write(alloc_id, range, machine.data_race.as_mut().unwrap())?;
774772
}
775773
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
776-
stacked_borrows.memory_written(
774+
stacked_borrows.get_mut().memory_written(
777775
alloc_id,
778776
tag,
779777
range,
@@ -802,7 +800,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
802800
data_race.deallocate(alloc_id, range, machine.data_race.as_mut().unwrap())?;
803801
}
804802
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
805-
stacked_borrows.memory_deallocated(
803+
stacked_borrows.get_mut().memory_deallocated(
806804
alloc_id,
807805
tag,
808806
range,

0 commit comments

Comments
 (0)