Skip to content

Commit 66354f0

Browse files
committed
Auto merge of #2694 - RalfJung:retag-deref-check, r=saethlin
fix handling of spurious accesses during retag The `dereferenceable` attribute we emit for LLVM is checked during retag in Stacked Borrows. However, we currently don't properly do that for retagging of `&mut !Unpin`, which this PR fixes. Also this adjusts retagging to inform the data race model of the accesses as well. Fixes rust-lang/miri#2648. Also fixes rust-lang/miri#2693 since the same issue arose for retagging as well. r? `@saethlin`
2 parents a83b105 + edf8154 commit 66354f0

40 files changed

+339
-157
lines changed

src/tools/miri/src/concurrency/data_race.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -838,18 +838,18 @@ impl VClockAlloc {
838838
&self,
839839
alloc_id: AllocId,
840840
range: AllocRange,
841-
global: &GlobalState,
842-
thread_mgr: &ThreadManager<'_, '_>,
841+
machine: &MiriMachine<'_, '_>,
843842
) -> InterpResult<'tcx> {
843+
let global = machine.data_race.as_ref().unwrap();
844844
if global.race_detecting() {
845-
let (index, clocks) = global.current_thread_state(thread_mgr);
845+
let (index, clocks) = global.current_thread_state(&machine.threads);
846846
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
847847
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
848848
if let Err(DataRace) = range.read_race_detect(&clocks, index) {
849849
// Report data-race.
850850
return Self::report_data_race(
851851
global,
852-
thread_mgr,
852+
&machine.threads,
853853
range,
854854
"Read",
855855
false,
@@ -869,17 +869,17 @@ impl VClockAlloc {
869869
alloc_id: AllocId,
870870
range: AllocRange,
871871
write_type: WriteType,
872-
global: &mut GlobalState,
873-
thread_mgr: &ThreadManager<'_, '_>,
872+
machine: &mut MiriMachine<'_, '_>,
874873
) -> InterpResult<'tcx> {
874+
let global = machine.data_race.as_mut().unwrap();
875875
if global.race_detecting() {
876-
let (index, clocks) = global.current_thread_state(thread_mgr);
876+
let (index, clocks) = global.current_thread_state(&machine.threads);
877877
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
878878
if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
879879
// Report data-race
880880
return Self::report_data_race(
881881
global,
882-
thread_mgr,
882+
&machine.threads,
883883
range,
884884
write_type.get_descriptor(),
885885
false,
@@ -901,10 +901,9 @@ impl VClockAlloc {
901901
&mut self,
902902
alloc_id: AllocId,
903903
range: AllocRange,
904-
global: &mut GlobalState,
905-
thread_mgr: &ThreadManager<'_, '_>,
904+
machine: &mut MiriMachine<'_, '_>,
906905
) -> InterpResult<'tcx> {
907-
self.unique_access(alloc_id, range, WriteType::Write, global, thread_mgr)
906+
self.unique_access(alloc_id, range, WriteType::Write, machine)
908907
}
909908

910909
/// Detect data-races for an unsynchronized deallocate operation, will not perform
@@ -915,10 +914,9 @@ impl VClockAlloc {
915914
&mut self,
916915
alloc_id: AllocId,
917916
range: AllocRange,
918-
global: &mut GlobalState,
919-
thread_mgr: &ThreadManager<'_, '_>,
917+
machine: &mut MiriMachine<'_, '_>,
920918
) -> InterpResult<'tcx> {
921-
self.unique_access(alloc_id, range, WriteType::Deallocate, global, thread_mgr)
919+
self.unique_access(alloc_id, range, WriteType::Deallocate, machine)
922920
}
923921
}
924922

src/tools/miri/src/machine.rs

+7-33
Original file line numberDiff line numberDiff line change
@@ -1003,21 +1003,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
10031003
range: AllocRange,
10041004
) -> InterpResult<'tcx> {
10051005
if let Some(data_race) = &alloc_extra.data_race {
1006-
data_race.read(
1007-
alloc_id,
1008-
range,
1009-
machine.data_race.as_ref().unwrap(),
1010-
&machine.threads,
1011-
)?;
1006+
data_race.read(alloc_id, range, machine)?;
10121007
}
10131008
if let Some(stacked_borrows) = &alloc_extra.stacked_borrows {
1014-
stacked_borrows.borrow_mut().before_memory_read(
1015-
alloc_id,
1016-
prov_extra,
1017-
range,
1018-
machine.stacked_borrows.as_ref().unwrap(),
1019-
machine,
1020-
)?;
1009+
stacked_borrows
1010+
.borrow_mut()
1011+
.before_memory_read(alloc_id, prov_extra, range, machine)?;
10211012
}
10221013
if let Some(weak_memory) = &alloc_extra.weak_memory {
10231014
weak_memory.memory_accessed(range, machine.data_race.as_ref().unwrap());
@@ -1034,21 +1025,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
10341025
range: AllocRange,
10351026
) -> InterpResult<'tcx> {
10361027
if let Some(data_race) = &mut alloc_extra.data_race {
1037-
data_race.write(
1038-
alloc_id,
1039-
range,
1040-
machine.data_race.as_mut().unwrap(),
1041-
&machine.threads,
1042-
)?;
1028+
data_race.write(alloc_id, range, machine)?;
10431029
}
10441030
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
1045-
stacked_borrows.get_mut().before_memory_write(
1046-
alloc_id,
1047-
prov_extra,
1048-
range,
1049-
machine.stacked_borrows.as_ref().unwrap(),
1050-
machine,
1051-
)?;
1031+
stacked_borrows.get_mut().before_memory_write(alloc_id, prov_extra, range, machine)?;
10521032
}
10531033
if let Some(weak_memory) = &alloc_extra.weak_memory {
10541034
weak_memory.memory_accessed(range, machine.data_race.as_ref().unwrap());
@@ -1068,19 +1048,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
10681048
machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id));
10691049
}
10701050
if let Some(data_race) = &mut alloc_extra.data_race {
1071-
data_race.deallocate(
1072-
alloc_id,
1073-
range,
1074-
machine.data_race.as_mut().unwrap(),
1075-
&machine.threads,
1076-
)?;
1051+
data_race.deallocate(alloc_id, range, machine)?;
10771052
}
10781053
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
10791054
stacked_borrows.get_mut().before_memory_deallocation(
10801055
alloc_id,
10811056
prove_extra,
10821057
range,
1083-
machine.stacked_borrows.as_ref().unwrap(),
10841058
machine,
10851059
)
10861060
} else {

src/tools/miri/src/stacked_borrows/diagnostics.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,12 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
353353

354354
/// Report a descriptive error when `new` could not be granted from `derived_from`.
355355
#[inline(never)] // This is only called on fatal code paths
356-
pub(super) fn grant_error(&self, perm: Permission, stack: &Stack) -> InterpError<'tcx> {
356+
pub(super) fn grant_error(&self, stack: &Stack) -> InterpError<'tcx> {
357357
let Operation::Retag(op) = &self.operation else {
358358
unreachable!("grant_error should only be called during a retag")
359359
};
360+
let perm =
361+
op.permission.expect("`start_grant` must be called before calling `grant_error`");
360362
let action = format!(
361363
"trying to retag from {:?} for {:?} permission at {:?}[{:#x}]",
362364
op.orig_tag,
@@ -374,8 +376,11 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
374376
/// Report a descriptive error when `access` is not permitted based on `tag`.
375377
#[inline(never)] // This is only called on fatal code paths
376378
pub(super) fn access_error(&self, stack: &Stack) -> InterpError<'tcx> {
377-
let Operation::Access(op) = &self.operation else {
378-
unreachable!("access_error should only be called during an access")
379+
// Deallocation and retagging also do an access as part of their thing, so handle that here, too.
380+
let op = match &self.operation {
381+
Operation::Access(op) => op,
382+
Operation::Retag(_) => return self.grant_error(stack),
383+
Operation::Dealloc(_) => return self.dealloc_error(stack),
379384
};
380385
let action = format!(
381386
"attempting a {access} using {tag:?} at {alloc_id:?}[{offset:#x}]",
@@ -428,14 +433,16 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
428433
}
429434

430435
#[inline(never)] // This is only called on fatal code paths
431-
pub fn dealloc_error(&self) -> InterpError<'tcx> {
436+
pub fn dealloc_error(&self, stack: &Stack) -> InterpError<'tcx> {
432437
let Operation::Dealloc(op) = &self.operation else {
433438
unreachable!("dealloc_error should only be called during a deallocation")
434439
};
435440
err_sb_ub(
436441
format!(
437-
"no item granting write access for deallocation to tag {:?} at {:?} found in borrow stack",
438-
op.tag, self.history.id,
442+
"attempting deallocation using {tag:?} at {alloc_id:?}{cause}",
443+
tag = op.tag,
444+
alloc_id = self.history.id,
445+
cause = error_cause(stack, op.tag),
439446
),
440447
None,
441448
op.tag.and_then(|tag| self.get_logs_relevant_to(tag, None)),

0 commit comments

Comments
 (0)