Skip to content

Commit 34392a9

Browse files
committed
Fix(alloc): Correctly handle ZST alignment for IntoIter::nth_back
This commit consolidates all changes, including the core logic fix for IntoIter::nth_back and the addition of the Miri regression test in `library/alloctests/tests/vec.rs`, to prevent Undefined Behavior (UB) when dealing with highly-aligned Zero-Sized Types.
1 parent 467250d commit 34392a9

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

‎library/alloc/src/vec/into_iter.rs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,12 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
411411
// SAFETY: same as for advance_by()
412412
self.end = unsafe { self.end.sub(step_size) };
413413
}
414-
let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size);
414+
let to_drop = if T::IS_ZST {
415+
// ZST may cause unalignment
416+
ptr::slice_from_raw_parts_mut(ptr::NonNull::<T>::dangling().as_ptr(), step_size)
417+
} else {
418+
ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size)
419+
};
415420
// SAFETY: same as for advance_by()
416421
unsafe {
417422
ptr::drop_in_place(to_drop);

‎library/alloctests/tests/vec.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2717,3 +2717,35 @@ fn vec_null_ptr_roundtrip() {
27172717
let new = roundtripped.with_addr(ptr.addr());
27182718
unsafe { new.read() };
27192719
}
2720+
2721+
// Regression test for Undefined Behavior (UB) caused by IntoIter::nth_back (#148682)
2722+
// when dealing with high-aligned Zero-Sized Types (ZSTs).
2723+
use std::collections::{BTreeMap, BinaryHeap, HashMap, LinkedList, VecDeque};
2724+
#[test]
2725+
fn zst_collections_iter_nth_back_regression() {
2726+
#[repr(align(8))]
2727+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
2728+
struct Thing;
2729+
let v = vec![Thing, Thing];
2730+
let _ = v.into_iter().nth_back(1);
2731+
let mut d = VecDeque::new();
2732+
d.push_back(Thing);
2733+
d.push_back(Thing);
2734+
let _ = d.into_iter().nth_back(1);
2735+
let mut map = BTreeMap::new();
2736+
map.insert(0, Thing);
2737+
map.insert(1, Thing);
2738+
let _ = map.into_values().nth_back(0);
2739+
let mut hash_map = HashMap::new();
2740+
hash_map.insert(1, Thing);
2741+
hash_map.insert(2, Thing);
2742+
let _ = hash_map.into_values().nth(1);
2743+
let mut heap = BinaryHeap::new();
2744+
heap.push(Thing);
2745+
heap.push(Thing);
2746+
let _ = heap.into_iter().nth_back(1);
2747+
let mut list = LinkedList::new();
2748+
list.push_back(Thing);
2749+
list.push_back(Thing);
2750+
let _ = list.into_iter().nth_back(1);
2751+
}

0 commit comments

Comments
 (0)