Skip to content

Commit

Permalink
Rollup merge of #106084 - RalfJung:into-iter, r=thomcc
Browse files Browse the repository at this point in the history
fix vec::IntoIter::drop on high-alignment ZST

This fixes a soundness bug: IntoIter would call `drop_in_place` on an insufficiently aligned pointer. So if a ZST with alignment greater 1 had drop glue, that would be called with an unaligned reference. Since rust-lang/rust#103957, Miri checks alignment even if the type does not have drop glue, which is how this bug was found.

r? ``@thomcc``
  • Loading branch information
matthiaskrgr committed Dec 23, 2022
2 parents a7e05f6 + bf5fefe commit c765c7e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ Definite bugs found:
* [Data race in `thread::scope`](https://github.com/rust-lang/rust/issues/98498)
* [`regex` incorrectly handling unaligned `Vec<u8>` buffers](https://www.reddit.com/r/rust/comments/vq3mmu/comment/ienc7t0?context=3)
* [Incorrect use of `compare_exchange_weak` in `once_cell`](https://github.com/matklad/once_cell/issues/186)
* [Dropping with unaligned pointers in `vec::IntoIter`](https://github.com/rust-lang/rust/pull/106084)

Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):

Expand Down
32 changes: 25 additions & 7 deletions tests/pass/vec.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@compile-flags: -Zmiri-strict-provenance
#![feature(iter_advance_by, iter_next_chunk)]

// Gather all references from a mutable iterator and make sure Miri notices if
// using them is dangerous.
fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
Expand Down Expand Up @@ -37,15 +39,31 @@ fn vec_into_iter() -> u8 {
}

fn vec_into_iter_rev() -> u8 {
vec![1, 2, 3, 4].into_iter().map(|x| x * x).fold(0, |x, y| x + y)
vec![1, 2, 3, 4].into_iter().rev().map(|x| x * x).fold(0, |x, y| x + y)
}

fn vec_into_iter_zst() -> usize {
vec![[0u64; 0], [0u64; 0]].into_iter().rev().map(|x| x.len()).sum()
fn vec_into_iter_zst() {
for _ in vec![[0u64; 0]].into_iter() {}
let v = vec![[0u64; 0], [0u64; 0]].into_iter().map(|x| x.len()).sum::<usize>();
assert_eq!(v, 0);

let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
it.advance_by(1);
drop(it);

let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
it.next_chunk::<1>().unwrap();
drop(it);

let mut it = vec![[0u64; 0], [0u64; 0]].into_iter();
it.next_chunk::<4>().unwrap_err();
drop(it);
}

fn vec_into_iter_rev_zst() -> usize {
vec![[0u64; 0], [0u64; 0]].into_iter().rev().map(|x| x.len()).sum()
fn vec_into_iter_rev_zst() {
for _ in vec![[0u64; 0]; 5].into_iter().rev() {}
let v = vec![[0u64; 0], [0u64; 0]].into_iter().rev().map(|x| x.len()).sum::<usize>();
assert_eq!(v, 0);
}

fn vec_iter_and_mut() {
Expand Down Expand Up @@ -150,8 +168,8 @@ fn main() {
assert_eq!(vec_into_iter(), 30);
assert_eq!(vec_into_iter_rev(), 30);
vec_iter_and_mut();
assert_eq!(vec_into_iter_zst(), 0);
assert_eq!(vec_into_iter_rev_zst(), 0);
vec_into_iter_zst();
vec_into_iter_rev_zst();
vec_iter_and_mut_rev();

assert_eq!(make_vec().capacity(), 4);
Expand Down

0 comments on commit c765c7e

Please sign in to comment.