Skip to content

Commit

Permalink
Auto merge of #1725 - RalfJung:zst-reborrow, r=RalfJung
Browse files Browse the repository at this point in the history
fix reborrowing of tagged ZST references

`@SkiFire13` [pointed out](rust-lang/rust#82554 (comment)) that Miri fails to detect illegal use of empty slices. This PR fixes that. In so doing, it uncovers a flaw of Stacked Borrows: it is incompatible with how the formatting machinery uses `extern type`, so for now we skip reborrowing when we cannot determine the exact size of the pointee.
  • Loading branch information
bors committed Feb 27, 2021
2 parents 74b7714 + 48f7c8e commit 4ecb5a9
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 4 deletions.
16 changes: 12 additions & 4 deletions src/stacked_borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,15 +586,23 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let place = this.ref_to_mplace(val)?;
let size = this
.size_and_align_of_mplace(&place)?
.map(|(size, _)| size)
.unwrap_or_else(|| place.layout.size);
.map(|(size, _)| size);
// FIXME: If we cannot determine the size (because the unsized tail is an `extern type`),
// bail out -- we cannot reasonably figure out which memory range to reborrow.
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/276.
let size = match size {
Some(size) => size,
None => return Ok(*val),
};
// `reborrow` relies on getting a `Pointer` and everything being in-bounds,
// so let's ensure that. However, we do not care about alignment.
// We can see dangling ptrs in here e.g. after a Box's `Unique` was
// updated using "self.0 = ..." (can happen in Box::from_raw) so we cannot ICE; see miri#1050.
let place = this.mplace_access_checked(place, Some(Align::from_bytes(1).unwrap()))?;
// Nothing to do for ZSTs.
if size == Size::ZERO {
// Nothing to do for ZSTs. We use `is_bits` here because we *do* need to retag even ZSTs
// when there actually is a tag (to avoid inheriting a tag that would let us access more
// than 0 bytes).
if size == Size::ZERO && place.ptr.is_bits() {
return Ok(*val);
}

Expand Down
11 changes: 11 additions & 0 deletions tests/compile-fail/stacked_borrows/zst_slice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// compile-flags: -Zmiri-track-raw-pointers
// error-pattern: does not have an appropriate item in the borrow stack

fn main() {
unsafe {
let a = [1, 2, 3];
let s = &a[0..0];
assert_eq!(s.len(), 0);
assert_eq!(*s.get_unchecked(1), 2);
}
}

0 comments on commit 4ecb5a9

Please sign in to comment.