Skip to content

Commit 85593a4

Browse files
committed
Fix potential buffer overflow in insert_many
Fixes #252.
1 parent 0b2b4e5 commit 85593a4

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/lib.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -1041,14 +1041,24 @@ impl<A: Array> SmallVec<A> {
10411041
let mut cur = ptr.add(num_added);
10421042
if num_added >= lower_size_bound {
10431043
// Iterator provided more elements than the hint. Move trailing items again.
1044+
1045+
// `reserve` needs `len` to be accurate.
1046+
self.set_len(old_len + num_added);
1047+
let guard_len = guard.len;
1048+
guard.len = 0; // in case `reserve` panics, don't double-free in guard.drop().
1049+
1050+
// Grow the vector by 1.
10441051
self.reserve(1);
1052+
10451053
let start = self.as_mut_ptr();
10461054
ptr = start.add(index);
10471055
cur = ptr.add(num_added);
10481056
ptr::copy(cur, cur.add(1), old_len - index);
10491057

1058+
// Restore the guard.
1059+
self.set_len(0);
10501060
guard.start = start;
1051-
guard.len += 1;
1061+
guard.len = guard_len + 1;
10521062
guard.skip.end += 1;
10531063
}
10541064
ptr::write(cur, element);

src/tests.rs

+15
Original file line numberDiff line numberDiff line change
@@ -905,3 +905,18 @@ fn empty_macro() {
905905
fn zero_size_items() {
906906
SmallVec::<[(); 0]>::new().push(());
907907
}
908+
909+
#[test]
910+
fn test_insert_many_overflow() {
911+
let mut v: SmallVec<[u8; 0]> = SmallVec::new();
912+
913+
// Spill on heap
914+
v.push(123);
915+
916+
// Prepare an iterator with small lower bound
917+
let iter = (0u8..=255).filter(|n| n % 2 == 0);
918+
assert_eq!(iter.size_hint().0, 0);
919+
920+
// Triggering the bug
921+
v.insert_many(0, iter);
922+
}

0 commit comments

Comments
 (0)