Rollup merge of #149272 - DrAsu33:fix-vec-iter-zst-alignment-148682, r=Mark-Simulacrum

Fix vec iter zst alignment

Closes rust-lang/rust#148682
This commit is contained in:
Chris Denton 2025-12-14 09:18:28 +00:00 committed by GitHub
commit 735c45eda4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 38 additions and 1 deletions

View file

@ -411,7 +411,12 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
// SAFETY: same as for advance_by()
self.end = unsafe { self.end.sub(step_size) };
}
let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size);
let to_drop = if T::IS_ZST {
// ZST may cause unalignment
ptr::slice_from_raw_parts_mut(ptr::NonNull::<T>::dangling().as_ptr(), step_size)
} else {
ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size)
};
// SAFETY: same as for advance_by()
unsafe {
ptr::drop_in_place(to_drop);

View file

@ -2717,3 +2717,35 @@ fn vec_null_ptr_roundtrip() {
let new = roundtripped.with_addr(ptr.addr());
unsafe { new.read() };
}
// Regression test for Undefined Behavior (UB) caused by IntoIter::nth_back (#148682)
// when dealing with high-aligned Zero-Sized Types (ZSTs).
use std::collections::{BTreeMap, BinaryHeap, HashMap, LinkedList, VecDeque};
#[test]
fn zst_collections_iter_nth_back_regression() {
#[repr(align(8))]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
struct Thing;
let v = vec![Thing, Thing];
let _ = v.into_iter().nth_back(1);
let mut d = VecDeque::new();
d.push_back(Thing);
d.push_back(Thing);
let _ = d.into_iter().nth_back(1);
let mut map = BTreeMap::new();
map.insert(0, Thing);
map.insert(1, Thing);
let _ = map.into_values().nth_back(0);
let mut hash_map = HashMap::new();
hash_map.insert(1, Thing);
hash_map.insert(2, Thing);
let _ = hash_map.into_values().nth(1);
let mut heap = BinaryHeap::new();
heap.push(Thing);
heap.push(Thing);
let _ = heap.into_iter().nth_back(1);
let mut list = LinkedList::new();
list.push_back(Thing);
list.push_back(Thing);
let _ = list.into_iter().nth_back(1);
}