Skip to content

Commit dc1069d

Browse files
committed
fix reborrowing of tagged ZST references
1 parent 74b7714 commit dc1069d

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

src/stacked_borrows.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -586,15 +586,22 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
586586
let place = this.ref_to_mplace(val)?;
587587
let size = this
588588
.size_and_align_of_mplace(&place)?
589-
.map(|(size, _)| size)
590-
.unwrap_or_else(|| place.layout.size);
589+
.map(|(size, _)| size);
590+
// FIXME: If we cannot determine the size (because the unsized tail is an `extern type`),
591+
// bail out -- we cannot reasonably figure out which memory range to reborrow.
592+
let size = match size {
593+
Some(size) => size,
594+
None => return Ok(*val),
595+
};
591596
// `reborrow` relies on getting a `Pointer` and everything being in-bounds,
592597
// so let's ensure that. However, we do not care about alignment.
593598
// We can see dangling ptrs in here e.g. after a Box's `Unique` was
594599
// updated using "self.0 = ..." (can happen in Box::from_raw) so we cannot ICE; see miri#1050.
595600
let place = this.mplace_access_checked(place, Some(Align::from_bytes(1).unwrap()))?;
596-
// Nothing to do for ZSTs.
597-
if size == Size::ZERO {
601+
// Nothing to do for ZSTs. We use `is_bits` here because we *do* need to retag even ZSTs
602+
// when there actually is a tag (to avoid inheriting a tag that would let us access more
603+
// than 0 bytes).
604+
if size == Size::ZERO && place.ptr.is_bits() {
598605
return Ok(*val);
599606
}
600607

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile-flags: -Zmiri-track-raw-pointers
2+
// error-pattern: does not have an appropriate item in the borrow stack
3+
4+
fn main() {
5+
unsafe {
6+
let a = [1, 2, 3];
7+
let s = &a[0..0];
8+
assert_eq!(s.len(), 0);
9+
assert_eq!(*s.get_unchecked(1), 2);
10+
}
11+
}

0 commit comments

Comments
 (0)