Skip to content

Commit 50f19e3

Browse files
committed
Try to add some diagnostics for protectors too
1 parent 4d3f3da commit 50f19e3

File tree

2 files changed

+95
-22
lines changed

2 files changed

+95
-22
lines changed

src/diagnostics.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,19 @@ pub fn report_error<'tcx, 'mir>(
164164
(None, format!("see {} for further information", url)),
165165
];
166166
match history {
167-
Some(TagHistory::Tagged {tag, created: (created_range, created_span), invalidated}) => {
167+
Some(TagHistory::Tagged {tag, created: (created_range, created_span), invalidated, protected }) => {
168168
let msg = format!("{:?} was created due to a retag at offsets {}", tag, HexRange(*created_range));
169169
helps.push((Some(created_span.clone()), msg));
170170
if let Some((invalidated_range, invalidated_span)) = invalidated {
171171
let msg = format!("{:?} was later invalidated due to a retag at offsets {}", tag, HexRange(*invalidated_range));
172172
helps.push((Some(invalidated_span.clone()), msg));
173173
}
174+
if let Some((protecting_tag, protecting_tag_span, protection_span)) = protected {
175+
helps.push((Some(protecting_tag_span.clone()), format!("{:?} was protected due to {:?} which was created here", tag, protecting_tag)));
176+
helps.push((Some(protection_span.clone()), "this protector is live for this call".to_string()));
177+
}
174178
}
175-
Some(TagHistory::Untagged{ recently_created, recently_invalidated, matching_created }) => {
179+
Some(TagHistory::Untagged{ recently_created, recently_invalidated, matching_created, protected }) => {
176180
if let Some((range, span)) = recently_created {
177181
let msg = format!("tag was most recently created at offsets {}", HexRange(*range));
178182
helps.push((Some(span.clone()), msg));
@@ -185,6 +189,10 @@ pub fn report_error<'tcx, 'mir>(
185189
let msg = format!("this tag was also created here at offsets {}", HexRange(*range));
186190
helps.push((Some(span.clone()), msg));
187191
}
192+
if let Some((protecting_tag, protecting_tag_span, protection_span)) = protected {
193+
helps.push((Some(protecting_tag_span.clone()), format!("{:?} was protected due to a tag which was created here", protecting_tag)));
194+
helps.push((Some(protection_span.clone()), "this protector is live for this call".to_string()));
195+
}
188196
}
189197
None => {}
190198
}

src/stacked_borrows.rs

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,20 @@ struct AllocHistory {
126126
current_time: usize,
127127
creations: Vec<Event>,
128128
invalidations: Vec<Event>,
129+
protectors: Vec<Protection>,
130+
}
131+
132+
#[derive(Debug)]
133+
struct Protection {
134+
orig_tag: SbTag,
135+
tag: SbTag,
136+
span: Span,
129137
}
130138

131139
#[derive(Debug)]
132140
struct Event {
133141
time: usize,
142+
parent: Option<SbTag>,
134143
tag: SbTag,
135144
range: AllocRange,
136145
span: Span,
@@ -141,11 +150,13 @@ pub enum TagHistory {
141150
tag: SbTag,
142151
created: (AllocRange, SpanData),
143152
invalidated: Option<(AllocRange, SpanData)>,
153+
protected: Option<(SbTag, SpanData, SpanData)>,
144154
},
145155
Untagged {
146156
recently_created: Option<(AllocRange, SpanData)>,
147157
recently_invalidated: Option<(AllocRange, SpanData)>,
148158
matching_created: Option<(AllocRange, SpanData)>,
159+
protected: Option<(SbTag, SpanData, SpanData)>,
149160
},
150161
}
151162

@@ -258,9 +269,16 @@ impl GlobalState {
258269
tag
259270
}
260271

261-
fn add_creation(&mut self, tag: SbTag, alloc: AllocId, range: AllocRange) {
272+
fn add_creation(
273+
&mut self,
274+
parent: Option<SbTag>,
275+
tag: SbTag,
276+
alloc: AllocId,
277+
range: AllocRange,
278+
) {
262279
let mut extras = self.extras.entry(alloc).or_default();
263280
extras.creations.push(Event {
281+
parent,
264282
tag,
265283
range,
266284
span: self.current_span,
@@ -272,6 +290,7 @@ impl GlobalState {
272290
fn add_invalidation(&mut self, tag: SbTag, alloc: AllocId, range: AllocRange) {
273291
let mut extras = self.extras.entry(alloc).or_default();
274292
extras.invalidations.push(Event {
293+
parent: None,
275294
tag,
276295
range,
277296
span: self.current_span,
@@ -280,14 +299,40 @@ impl GlobalState {
280299
extras.current_time += 1;
281300
}
282301

302+
fn add_protector(&mut self, orig_tag: SbTag, tag: SbTag, alloc: AllocId) {
303+
let mut extras = self.extras.entry(alloc).or_default();
304+
extras.protectors.push(Protection { orig_tag, tag, span: self.current_span });
305+
extras.current_time += 1;
306+
}
307+
283308
fn get_stack_history(
284309
&self,
285310
tag: SbTag,
286311
alloc: AllocId,
287312
alloc_range: AllocRange,
288313
offset: Size,
314+
protector_tag: Option<SbTag>,
289315
) -> Option<TagHistory> {
290316
let extras = self.extras.get(&alloc)?;
317+
let protected = protector_tag
318+
.and_then(|protector| {
319+
extras.protectors.iter().find_map(|protection| {
320+
if protection.tag == protector {
321+
Some((protection.orig_tag, protection.span.data()))
322+
} else {
323+
None
324+
}
325+
})
326+
})
327+
.and_then(|(tag, call_span)| {
328+
extras.creations.iter().rev().find_map(|event| {
329+
if event.tag == tag {
330+
Some((event.parent?, event.span.data(), call_span))
331+
} else {
332+
None
333+
}
334+
})
335+
});
291336
if let SbTag::Tagged(_) = tag {
292337
let get_matching = |events: &[Event]| {
293338
events.iter().rev().find_map(|event| {
@@ -296,8 +341,9 @@ impl GlobalState {
296341
};
297342
Some(TagHistory::Tagged {
298343
tag,
299-
created: get_matching(&extras.creations).unwrap(),
344+
created: get_matching(&extras.creations)?,
300345
invalidated: get_matching(&extras.invalidations),
346+
protected,
301347
})
302348
} else {
303349
let mut created_time = 0;
@@ -348,7 +394,12 @@ impl GlobalState {
348394
} else {
349395
None
350396
};
351-
Some(TagHistory::Untagged { recently_created, matching_created, recently_invalidated })
397+
Some(TagHistory::Untagged {
398+
recently_created,
399+
matching_created,
400+
recently_invalidated,
401+
protected,
402+
})
352403
}
353404
}
354405
}
@@ -446,27 +497,33 @@ impl<'tcx> Stack {
446497
/// `None` during a deallocation.
447498
fn check_protector(
448499
item: &Item,
449-
provoking_access: Option<(SbTag, AccessKind)>,
500+
provoking_access: Option<(SbTag, AllocId, AllocRange, Size)>, // just for debug printing amd error messages
450501
global: &GlobalState,
451502
) -> InterpResult<'tcx> {
452503
if let SbTag::Tagged(id) = item.tag {
453504
if Some(id) == global.tracked_pointer_tag {
454505
register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(
455506
item.clone(),
456-
provoking_access,
507+
None, // FIXME
457508
));
458509
}
459510
}
460511
if let Some(call) = item.protector {
461512
if global.is_active(call) {
462-
if let Some((tag, _)) = provoking_access {
513+
if let Some((tag, alloc_id, alloc_range, offset)) = provoking_access {
463514
Err(err_sb_ub(
464515
format!(
465516
"not granting access to tag {:?} because incompatible item is protected: {:?}",
466517
tag, item
467518
),
468519
None,
469-
None,
520+
global.get_stack_history(
521+
tag,
522+
alloc_id,
523+
alloc_range,
524+
offset,
525+
Some(item.tag),
526+
),
470527
))?
471528
} else {
472529
Err(err_sb_ub(
@@ -506,7 +563,7 @@ impl<'tcx> Stack {
506563
let first_incompatible_idx = self.find_first_write_incompatible(granting_idx);
507564
for item in self.borrows.drain(first_incompatible_idx..).rev() {
508565
trace!("access: popping item {:?}", item);
509-
Stack::check_protector(&item, Some((tag, access)), global)?;
566+
Stack::check_protector(&item, Some((tag, alloc_id, alloc_range, offset)), global)?;
510567
global.add_invalidation(item.tag, alloc_id, alloc_range);
511568
}
512569
} else {
@@ -522,7 +579,11 @@ impl<'tcx> Stack {
522579
let item = &mut self.borrows[idx];
523580
if item.perm == Permission::Unique {
524581
trace!("access: disabling item {:?}", item);
525-
Stack::check_protector(item, Some((tag, access)), global)?;
582+
Stack::check_protector(
583+
item,
584+
Some((tag, alloc_id, alloc_range, offset)),
585+
global,
586+
)?;
526587
item.perm = Permission::Disabled;
527588
global.add_invalidation(item.tag, alloc_id, alloc_range);
528589
}
@@ -548,7 +609,7 @@ impl<'tcx> Stack {
548609
tag, alloc_id,
549610
),
550611
None,
551-
global.get_stack_history(tag, alloc_id, alloc_range, offset),
612+
global.get_stack_history(tag, alloc_id, alloc_range, offset, None),
552613
)
553614
})?;
554615

@@ -640,7 +701,7 @@ impl<'tcx> Stack {
640701
err_sb_ub(
641702
format!("{}{}", action, self.error_cause(derived_from)),
642703
Some(Self::operation_summary("a reborrow", alloc_id, alloc_range)),
643-
global.get_stack_history(derived_from, alloc_id, alloc_range, error_offset),
704+
global.get_stack_history(derived_from, alloc_id, alloc_range, error_offset, None),
644705
)
645706
}
646707

@@ -664,7 +725,7 @@ impl<'tcx> Stack {
664725
err_sb_ub(
665726
format!("{}{}", action, self.error_cause(tag)),
666727
Some(Self::operation_summary("an access", alloc_id, alloc_range)),
667-
global.get_stack_history(tag, alloc_id, alloc_range, error_offset),
728+
global.get_stack_history(tag, alloc_id, alloc_range, error_offset, None),
668729
)
669730
}
670731

@@ -768,7 +829,7 @@ impl Stacks {
768829
(tag, Permission::SharedReadWrite)
769830
}
770831
};
771-
extra.add_creation(base_tag, id, alloc_range(Size::ZERO, size));
832+
extra.add_creation(None, base_tag, id, alloc_range(Size::ZERO, size));
772833
Stacks::new(size, perm, base_tag)
773834
}
774835

@@ -857,6 +918,17 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
857918
let (alloc_id, base_offset, ptr) = this.memory.ptr_get_alloc(place.ptr)?;
858919
let orig_tag = ptr.provenance.sb;
859920

921+
let mem_extra = this.memory.extra.stacked_borrows.as_mut().unwrap().get_mut();
922+
mem_extra.add_creation(
923+
Some(orig_tag),
924+
new_tag,
925+
alloc_id,
926+
alloc_range(base_offset, base_offset + size),
927+
);
928+
if protect {
929+
mem_extra.add_protector(orig_tag, new_tag, alloc_id);
930+
}
931+
860932
// Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
861933
let (alloc_size, _) =
862934
this.memory.get_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
@@ -959,9 +1031,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9591031
None => return Ok(*val),
9601032
};
9611033

962-
// May return Err for retags of size 0
963-
let alloc = this.memory.ptr_get_alloc(place.ptr);
964-
9651034
// Compute new borrow.
9661035
let mem_extra = this.memory.extra.stacked_borrows.as_mut().unwrap().get_mut();
9671036
let new_tag = match kind {
@@ -971,10 +1040,6 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9711040
_ => SbTag::Tagged(mem_extra.new_ptr()),
9721041
};
9731042

974-
if let Ok((alloc_id, base_offset, _ptr)) = alloc {
975-
mem_extra.add_creation(new_tag, alloc_id, alloc_range(base_offset, base_offset + size));
976-
}
977-
9781043
// Reborrow.
9791044
this.reborrow(&place, size, kind, new_tag, protect)?;
9801045

0 commit comments

Comments
 (0)