|
0 |
Debian patch for bug 984665
|
|
1 |
|
|
2 |
The patches to lib.rs and tests.rs are identical to the upstream
|
|
3 |
commit described below. The changes to Cargo.toml (which were
|
|
4 |
just a change of the package version number) have been excluded.
|
|
5 |
|
|
6 |
commit 9998ba0694a6b51aa6604748b00b6a98f0a0039e
|
|
7 |
Author: Matt Brubeck <mbrubeck@limpet.net>
|
|
8 |
Date: Thu Jan 7 21:28:46 2021 -0800
|
|
9 |
|
|
10 |
Fix potential buffer overflow in `insert_many`
|
|
11 |
|
|
12 |
Fixes #252.
|
|
13 |
|
|
14 |
diff --git a/src/lib.rs b/src/lib.rs
|
|
15 |
index 0241aefa..5e9de828 100644
|
|
16 |
--- a/src/lib.rs
|
|
17 |
+++ b/src/lib.rs
|
|
18 |
@@ -1009,7 +1009,7 @@ impl<A: Array> SmallVec<A> {
|
|
19 |
/// Insert multiple elements at position `index`, shifting all following elements toward the
|
|
20 |
/// back.
|
|
21 |
pub fn insert_many<I: IntoIterator<Item = A::Item>>(&mut self, index: usize, iterable: I) {
|
|
22 |
- let iter = iterable.into_iter();
|
|
23 |
+ let mut iter = iterable.into_iter();
|
|
24 |
if index == self.len() {
|
|
25 |
return self.extend(iter);
|
|
26 |
}
|
|
27 |
@@ -1017,13 +1017,16 @@ impl<A: Array> SmallVec<A> {
|
|
28 |
let (lower_size_bound, _) = iter.size_hint();
|
|
29 |
assert!(lower_size_bound <= core::isize::MAX as usize); // Ensure offset is indexable
|
|
30 |
assert!(index + lower_size_bound >= index); // Protect against overflow
|
|
31 |
- self.reserve(lower_size_bound);
|
|
32 |
+
|
|
33 |
+ let mut num_added = 0;
|
|
34 |
+ let old_len = self.len();
|
|
35 |
+ assert!(index <= old_len);
|
|
36 |
|
|
37 |
unsafe {
|
|
38 |
- let old_len = self.len();
|
|
39 |
- assert!(index <= old_len);
|
|
40 |
+ // Reserve space for `lower_size_bound` elements.
|
|
41 |
+ self.reserve(lower_size_bound);
|
|
42 |
let start = self.as_mut_ptr();
|
|
43 |
- let mut ptr = start.add(index);
|
|
44 |
+ let ptr = start.add(index);
|
|
45 |
|
|
46 |
// Move the trailing elements.
|
|
47 |
ptr::copy(ptr, ptr.add(lower_size_bound), old_len - index);
|
|
48 |
@@ -1036,42 +1039,39 @@ impl<A: Array> SmallVec<A> {
|
|
49 |
len: old_len + lower_size_bound,
|
|
50 |
};
|
|
51 |
|
|
52 |
- let mut num_added = 0;
|
|
53 |
- for element in iter {
|
|
54 |
- let mut cur = ptr.add(num_added);
|
|
55 |
- if num_added >= lower_size_bound {
|
|
56 |
- // Iterator provided more elements than the hint. Move trailing items again.
|
|
57 |
- self.reserve(1);
|
|
58 |
- let start = self.as_mut_ptr();
|
|
59 |
- ptr = start.add(index);
|
|
60 |
- cur = ptr.add(num_added);
|
|
61 |
- ptr::copy(cur, cur.add(1), old_len - index);
|
|
62 |
-
|
|
63 |
- guard.start = start;
|
|
64 |
- guard.len += 1;
|
|
65 |
- guard.skip.end += 1;
|
|
66 |
- }
|
|
67 |
+ while num_added < lower_size_bound {
|
|
68 |
+ let element = match iter.next() {
|
|
69 |
+ Some(x) => x,
|
|
70 |
+ None => break,
|
|
71 |
+ };
|
|
72 |
+ let cur = ptr.add(num_added);
|
|
73 |
ptr::write(cur, element);
|
|
74 |
guard.skip.start += 1;
|
|
75 |
num_added += 1;
|
|
76 |
}
|
|
77 |
- mem::forget(guard);
|
|
78 |
|
|
79 |
if num_added < lower_size_bound {
|
|
80 |
- // Iterator provided fewer elements than the hint
|
|
81 |
+ // Iterator provided fewer elements than the hint. Move the tail backward.
|
|
82 |
ptr::copy(
|
|
83 |
ptr.add(lower_size_bound),
|
|
84 |
ptr.add(num_added),
|
|
85 |
old_len - index,
|
|
86 |
);
|
|
87 |
}
|
|
88 |
-
|
|
89 |
+ // There are no more duplicate or uninitialized slots, so the guard is not needed.
|
|
90 |
self.set_len(old_len + num_added);
|
|
91 |
+ mem::forget(guard);
|
|
92 |
+ }
|
|
93 |
+
|
|
94 |
+ // Insert any remaining elements one-by-one.
|
|
95 |
+ for element in iter {
|
|
96 |
+ self.insert(index + num_added, element);
|
|
97 |
+ num_added += 1;
|
|
98 |
}
|
|
99 |
|
|
100 |
struct DropOnPanic<T> {
|
|
101 |
start: *mut T,
|
|
102 |
- skip: Range<usize>,
|
|
103 |
+ skip: Range<usize>, // Space we copied-out-of, but haven't written-to yet.
|
|
104 |
len: usize,
|
|
105 |
}
|
|
106 |
|
|
107 |
diff --git a/src/tests.rs b/src/tests.rs
|
|
108 |
index 0452ae85..19f6da85 100644
|
|
109 |
--- a/src/tests.rs
|
|
110 |
+++ b/src/tests.rs
|
|
111 |
@@ -905,3 +905,16 @@ fn empty_macro() {
|
|
112 |
fn zero_size_items() {
|
|
113 |
SmallVec::<[(); 0]>::new().push(());
|
|
114 |
}
|
|
115 |
+
|
|
116 |
+#[test]
|
|
117 |
+fn test_insert_many_overflow() {
|
|
118 |
+ let mut v: SmallVec<[u8; 1]> = SmallVec::new();
|
|
119 |
+ v.push(123);
|
|
120 |
+
|
|
121 |
+ // Prepare an iterator with small lower bound
|
|
122 |
+ let iter = (0u8..5).filter(|n| n % 2 == 0);
|
|
123 |
+ assert_eq!(iter.size_hint().0, 0);
|
|
124 |
+
|
|
125 |
+ v.insert_many(0, iter);
|
|
126 |
+ assert_eq!(&*v, &[0, 2, 4, 123]);
|
|
127 |
+}
|