Skip to content

Commit 8d488f3

Browse files
author
blake2-ppc
committed
std::vec: Fix hazards with uint overflows in unsafe code
Issue #8742 Add the method `.reserve_additional(n: uint)`: Check for overflow in self.len() + n, and reserve that many elements (rounded up to next power of two). Does nothing if self.len() + n < self.capacity() already.
1 parent 2017cc3 commit 8d488f3

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

src/libstd/vec.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,7 @@ pub trait OwnedVector<T> {
12451245

12461246
fn reserve(&mut self, n: uint);
12471247
fn reserve_at_least(&mut self, n: uint);
1248+
fn reserve_additional(&mut self, n: uint);
12481249
fn capacity(&self) -> uint;
12491250
fn shrink_to_fit(&mut self);
12501251

@@ -1300,6 +1301,11 @@ impl<T> OwnedVector<T> for ~[T] {
13001301
* # Arguments
13011302
*
13021303
* * n - The number of elements to reserve space for
1304+
*
1305+
* # Failure
1306+
*
1307+
* This method always succeeds in reserving space for `n` elements, or it does
1308+
* not return.
13031309
*/
13041310
fn reserve(&mut self, n: uint) {
13051311
// Only make the (slow) call into the runtime if we have to
@@ -1340,7 +1346,26 @@ impl<T> OwnedVector<T> for ~[T] {
13401346
*/
13411347
#[inline]
13421348
fn reserve_at_least(&mut self, n: uint) {
1343-
self.reserve(uint::next_power_of_two(n));
1349+
self.reserve(uint::next_power_of_two_opt(n).unwrap_or(n));
1350+
}
1351+
1352+
/**
1353+
* Reserves capacity for at least `n` additional elements in the given vector.
1354+
*
1355+
* # Failure
1356+
*
1357+
* Fails if the new required capacity overflows uint.
1358+
*
1359+
* May also fail if `reserve` fails.
1360+
*/
1361+
#[inline]
1362+
fn reserve_additional(&mut self, n: uint) {
1363+
if self.capacity() - self.len() < n {
1364+
match self.len().checked_add(&n) {
1365+
None => fail!("vec::reserve_additional: `uint` overflow"),
1366+
Some(new_cap) => self.reserve_at_least(new_cap)
1367+
}
1368+
}
13441369
}
13451370

13461371
/// Returns the number of elements the vector can hold without reallocating.
@@ -1376,17 +1401,15 @@ impl<T> OwnedVector<T> for ~[T] {
13761401
let repr: **Box<Vec<()>> = cast::transmute(&mut *self);
13771402
let fill = (**repr).data.fill;
13781403
if (**repr).data.alloc <= fill {
1379-
let new_len = self.len() + 1;
1380-
self.reserve_at_least(new_len);
1404+
self.reserve_additional(1);
13811405
}
13821406

13831407
push_fast(self, t);
13841408
} else {
13851409
let repr: **Vec<()> = cast::transmute(&mut *self);
13861410
let fill = (**repr).fill;
13871411
if (**repr).alloc <= fill {
1388-
let new_len = self.len() + 1;
1389-
self.reserve_at_least(new_len);
1412+
self.reserve_additional(1);
13901413
}
13911414

13921415
push_fast(self, t);
@@ -1432,7 +1455,7 @@ impl<T> OwnedVector<T> for ~[T] {
14321455
let self_len = self.len();
14331456
let rhs_len = rhs.len();
14341457
let new_len = self_len + rhs_len;
1435-
self.reserve_at_least(new_len);
1458+
self.reserve_additional(rhs.len());
14361459
unsafe { // Note: infallible.
14371460
let self_p = vec::raw::to_mut_ptr(*self);
14381461
let rhs_p = vec::raw::to_ptr(rhs);

0 commit comments

Comments
 (0)