Skip to content

Commit aa589d3

Browse files
committed
Auto merge of rust-lang#2145 - saethlin:zero-size-creation, r=RalfJung
Save a created event for zero-size reborrows Currently, we don't save a created event for zero-sized reborrows. Attempting to use something from a zero-sized reborrow is surprisingly common, for example on `minimal-lexical==0.2.1` we previously just emit this: ``` Undefined Behavior: attempting a write access using <187021> at alloc72933[0x0], but that tag does not exist in the borrow stack for this location --> /root/rust/library/core/src/ptr/mod.rs:1287:9 | 1287 | copy_nonoverlapping(&src as *const T, dst, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | attempting a write access using <187021> at alloc72933[0x0], but that tag does not exist in the borrow stack for this location | this error occurs as part of an access at alloc72933[0x0..0x8] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information = note: inside `std::ptr::write::<u64>` at /root/rust/library/core/src/ptr/mod.rs:1287:9 note: inside `minimal_lexical::stackvec::StackVec::push_unchecked` at /root/build/src/stackvec.rs:82:13 --> /root/build/src/stackvec.rs:82:13 | 82 | ptr::write(self.as_mut_ptr().add(self.len()), value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... backtrace continues... ``` Which leaves us with the question "where did we make this pointer?" because for every other diagnostic you get a "was created by" note, so I suspect people might be tempted to think there is a Miri bug here. I certainly was. --- This code duplication is so awful, I'm going to take a look at cleaning it up later. The fact that `ptr_get_alloc_id` can fail in this situation makes things annoying.
2 parents 10cb09c + 9a1475d commit aa589d3

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

src/stacked_borrows.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,26 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
706706
) -> InterpResult<'tcx> {
707707
let this = self.eval_context_mut();
708708
if size == Size::ZERO {
709-
// Nothing to do for zero-sized accesses.
709+
// Don't update any stacks for a zero-sized access; borrow stacks are per-byte and this
710+
// touches no bytes so there is no stack to put this tag in.
711+
// However, if the pointer for this operation points at a real allocation we still
712+
// record where it was created so that we can issue a helpful diagnostic if there is an
713+
// attempt to use it for a non-zero-sized access.
714+
// Dangling slices are a common case here; it's valid to get their length but with raw
715+
// pointer tagging for example all calls to get_unchecked on them are invalid.
716+
if let Ok((alloc_id, base_offset, orig_tag)) = this.ptr_try_get_alloc_id(place.ptr) {
717+
let extra = this.get_alloc_extra(alloc_id)?;
718+
let stacked_borrows =
719+
extra.stacked_borrows.as_ref().expect("we should have Stacked Borrows data");
720+
let mut alloc_history = stacked_borrows.history.borrow_mut();
721+
alloc_history.log_creation(
722+
Some(orig_tag),
723+
new_tag,
724+
alloc_range(base_offset, Size::ZERO),
725+
&mut this.machine.current_span(),
726+
);
727+
}
728+
710729
trace!(
711730
"reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})",
712731
kind,

tests/compile-fail/stacked_borrows/zst_slice.stderr

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ error: Undefined Behavior: trying to reborrow <TAG> for SharedReadOnly permissio
22
|
33
= help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
44
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
5-
5+
help: <TAG> was created by a retag at offsets [0x0..0x0]
6+
--> $DIR/zst_slice.rs:LL:CC
7+
|
8+
LL | assert_eq!(*s.get_unchecked(1), 2);
9+
| ^^^^^^^^^^^^^^^^^^
610
= note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at rustc_src/src/slice/mod.rs:LL:CC
711
note: inside `main` at $DIR/zst_slice.rs:LL:CC
812
--> $DIR/zst_slice.rs:LL:CC

0 commit comments

Comments
 (0)