Skip to content

Commit e7c9861

Browse files
committed
Fixes to collections to accommodate arith-overflow changes.
* `collections::btree::node`: accommodate (transient) underflow. * `collections::btree::map`: avoid underflow during `fn next` for `BTreeMap::range` methods. * `collections::slice`: note that pnkfelix deliberately used `new_pos_wrapping` only once; the other cases of arithmetic do not over- nor underflow, which is a useful property to leave implicitly checked/documented via the remaining calls to `fn new_pos(..)`. * `collections::vec_deque` applied wrapping ops (somewhat blindly) to two implementation methods, and many tests. * `std::collections::hash::table` : Use `OverflowingOps` trait to track overflow during `calculate_offsets` and `calculate_allocation` functions.
1 parent cf18e9c commit e7c9861

File tree

5 files changed

+83
-56
lines changed

5 files changed

+83
-56
lines changed

src/libcollections/btree/map.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use core::fmt::Debug;
2525
use core::hash::{Hash, Hasher};
2626
use core::iter::{Map, FromIterator, IntoIterator};
2727
use core::ops::{Index, IndexMut};
28-
use core::{iter, fmt, mem};
28+
use core::{iter, fmt, mem, usize};
2929
use Bound::{self, Included, Excluded, Unbounded};
3030

3131
use borrow::Borrow;
@@ -1467,7 +1467,7 @@ macro_rules! range_impl {
14671467
$Range {
14681468
inner: AbsIter {
14691469
traversals: traversals,
1470-
size: 0, // unused
1470+
size: usize::MAX, // unused
14711471
}
14721472
}
14731473
}

src/libcollections/btree/node.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,8 @@ impl<K, V> Node<K, V> {
12151215
ptr::copy(
12161216
self.edges_mut().as_mut_ptr().offset(index as isize),
12171217
self.edges().as_ptr().offset(index as isize + 1),
1218-
self.len() - index + 1
1218+
// index can be == len+1, so do the +1 first to avoid underflow.
1219+
(self.len() + 1) - index
12191220
);
12201221

12211222
edge

src/libcollections/slice.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ use core::iter::{range_step, MultiplicativeIterator};
9696
use core::marker::Sized;
9797
use core::mem::size_of;
9898
use core::mem;
99+
use core::num::wrapping::WrappingOps;
99100
use core::ops::FnMut;
100101
use core::option::Option::{self, Some, None};
101102
use core::ptr::PtrExt;
@@ -1209,18 +1210,22 @@ struct SizeDirection {
12091210
impl Iterator for ElementSwaps {
12101211
type Item = (usize, usize);
12111212

1212-
#[inline]
1213+
// #[inline]
12131214
fn next(&mut self) -> Option<(usize, usize)> {
1215+
fn new_pos_wrapping(i: usize, s: Direction) -> usize {
1216+
i.wrapping_add(match s { Pos => 1, Neg => -1 })
1217+
}
1218+
12141219
fn new_pos(i: usize, s: Direction) -> usize {
1215-
i + match s { Pos => 1, Neg => -1 }
1220+
match s { Pos => i + 1, Neg => i - 1 }
12161221
}
12171222

12181223
// Find the index of the largest mobile element:
12191224
// The direction should point into the vector, and the
12201225
// swap should be with a smaller `size` element.
12211226
let max = self.sdir.iter().cloned().enumerate()
12221227
.filter(|&(i, sd)|
1223-
new_pos(i, sd.dir) < self.sdir.len() &&
1228+
new_pos_wrapping(i, sd.dir) < self.sdir.len() &&
12241229
self.sdir[new_pos(i, sd.dir)].size < sd.size)
12251230
.max_by(|&(_, sd)| sd.size);
12261231
match max {

src/libcollections/vec_deque.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use core::fmt;
2626
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
2727
use core::mem;
2828
use core::num::{Int, UnsignedInt};
29+
use core::num::wrapping::WrappingOps;
2930
use core::ops::{Index, IndexMut};
3031
use core::ptr::{self, Unique};
3132
use core::raw::Slice as RawSlice;
@@ -120,6 +121,20 @@ impl<T> VecDeque<T> {
120121
#[inline]
121122
fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }
122123

124+
/// Returns the index in the underlying buffer for a given logical element
125+
/// index + addend.
126+
#[inline]
127+
fn wrap_add(&self, idx: usize, addend: usize) -> usize {
128+
wrap_index(idx.wrapping_add(addend), self.cap)
129+
}
130+
131+
/// Returns the index in the underlying buffer for a given logical element
132+
/// index - subtrahend.
133+
#[inline]
134+
fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize {
135+
wrap_index(idx.wrapping_sub(subtrahend), self.cap)
136+
}
137+
123138
/// Copies a contiguous block of memory len long from src to dst
124139
#[inline]
125140
unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
@@ -197,7 +212,7 @@ impl<T> VecDeque<T> {
197212
#[stable(feature = "rust1", since = "1.0.0")]
198213
pub fn get(&self, i: usize) -> Option<&T> {
199214
if i < self.len() {
200-
let idx = self.wrap_index(self.tail + i);
215+
let idx = self.wrap_add(self.tail, i);
201216
unsafe { Some(&*self.ptr.offset(idx as isize)) }
202217
} else {
203218
None
@@ -227,7 +242,7 @@ impl<T> VecDeque<T> {
227242
#[stable(feature = "rust1", since = "1.0.0")]
228243
pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
229244
if i < self.len() {
230-
let idx = self.wrap_index(self.tail + i);
245+
let idx = self.wrap_add(self.tail, i);
231246
unsafe { Some(&mut *self.ptr.offset(idx as isize)) }
232247
} else {
233248
None
@@ -257,8 +272,8 @@ impl<T> VecDeque<T> {
257272
pub fn swap(&mut self, i: usize, j: usize) {
258273
assert!(i < self.len());
259274
assert!(j < self.len());
260-
let ri = self.wrap_index(self.tail + i);
261-
let rj = self.wrap_index(self.tail + j);
275+
let ri = self.wrap_add(self.tail, i);
276+
let rj = self.wrap_add(self.tail, j);
262277
unsafe {
263278
ptr::swap(self.ptr.offset(ri as isize), self.ptr.offset(rj as isize))
264279
}
@@ -427,7 +442,7 @@ impl<T> VecDeque<T> {
427442
// [. . . o o o o o o o . . . . . . ]
428443
// H T
429444
// [o o . o o o o o ]
430-
let len = self.wrap_index(self.head - target_cap);
445+
let len = self.wrap_sub(self.head, target_cap);
431446
unsafe {
432447
self.copy_nonoverlapping(0, target_cap, len);
433448
}
@@ -438,7 +453,7 @@ impl<T> VecDeque<T> {
438453
// [o o o o o . . . . . . . . . o o ]
439454
// H T
440455
// [o o o o o . o o ]
441-
debug_assert!(self.wrap_index(self.head - 1) < target_cap);
456+
debug_assert!(self.wrap_sub(self.head, 1) < target_cap);
442457
let len = self.cap - self.tail;
443458
let new_tail = target_cap - len;
444459
unsafe {
@@ -775,7 +790,7 @@ impl<T> VecDeque<T> {
775790
None
776791
} else {
777792
let tail = self.tail;
778-
self.tail = self.wrap_index(self.tail + 1);
793+
self.tail = self.wrap_add(self.tail, 1);
779794
unsafe { Some(self.buffer_read(tail)) }
780795
}
781796
}
@@ -799,7 +814,7 @@ impl<T> VecDeque<T> {
799814
debug_assert!(!self.is_full());
800815
}
801816

802-
self.tail = self.wrap_index(self.tail - 1);
817+
self.tail = self.wrap_sub(self.tail, 1);
803818
let tail = self.tail;
804819
unsafe { self.buffer_write(tail, t); }
805820
}
@@ -824,7 +839,7 @@ impl<T> VecDeque<T> {
824839
}
825840

826841
let head = self.head;
827-
self.head = self.wrap_index(self.head + 1);
842+
self.head = self.wrap_add(self.head, 1);
828843
unsafe { self.buffer_write(head, t) }
829844
}
830845

@@ -847,7 +862,7 @@ impl<T> VecDeque<T> {
847862
if self.is_empty() {
848863
None
849864
} else {
850-
self.head = self.wrap_index(self.head - 1);
865+
self.head = self.wrap_sub(self.head, 1);
851866
let head = self.head;
852867
unsafe { Some(self.buffer_read(head)) }
853868
}
@@ -971,7 +986,7 @@ impl<T> VecDeque<T> {
971986
// A - The element that should be after the insertion point
972987
// M - Indicates element was moved
973988

974-
let idx = self.wrap_index(self.tail + i);
989+
let idx = self.wrap_add(self.tail, i);
975990

976991
let distance_to_tail = i;
977992
let distance_to_head = self.len() - i;
@@ -990,7 +1005,7 @@ impl<T> VecDeque<T> {
9901005
// [A o o o o o o o . . . . . I]
9911006
//
9921007

993-
self.tail = self.wrap_index(self.tail - 1);
1008+
self.tail = self.wrap_sub(self.tail, 1);
9941009
},
9951010
(true, true, _) => unsafe {
9961011
// contiguous, insert closer to tail:
@@ -1012,7 +1027,7 @@ impl<T> VecDeque<T> {
10121027
// [o I A o o o o o . . . . . . . o]
10131028
// M M
10141029

1015-
let new_tail = self.wrap_index(self.tail - 1);
1030+
let new_tail = self.wrap_sub(self.tail, 1);
10161031

10171032
self.copy(new_tail, self.tail, 1);
10181033
// Already moved the tail, so we only copy `i - 1` elements.
@@ -1031,7 +1046,7 @@ impl<T> VecDeque<T> {
10311046
// M M M
10321047

10331048
self.copy(idx + 1, idx, self.head - idx);
1034-
self.head = self.wrap_index(self.head + 1);
1049+
self.head = self.wrap_add(self.head, 1);
10351050
},
10361051
(false, true, true) => unsafe {
10371052
// discontiguous, insert closer to tail, tail section:
@@ -1123,7 +1138,7 @@ impl<T> VecDeque<T> {
11231138
}
11241139

11251140
// tail might've been changed so we need to recalculate
1126-
let new_idx = self.wrap_index(self.tail + i);
1141+
let new_idx = self.wrap_add(self.tail, i);
11271142
unsafe {
11281143
self.buffer_write(new_idx, t);
11291144
}
@@ -1170,7 +1185,7 @@ impl<T> VecDeque<T> {
11701185
// R - Indicates element that is being removed
11711186
// M - Indicates element was moved
11721187

1173-
let idx = self.wrap_index(self.tail + i);
1188+
let idx = self.wrap_add(self.tail, i);
11741189

11751190
let elem = unsafe {
11761191
Some(self.buffer_read(idx))
@@ -1219,7 +1234,7 @@ impl<T> VecDeque<T> {
12191234
// M M
12201235

12211236
self.copy(self.tail + 1, self.tail, i);
1222-
self.tail = self.wrap_index(self.tail + 1);
1237+
self.tail = self.wrap_add(self.tail, 1);
12231238
},
12241239
(false, false, false) => unsafe {
12251240
// discontiguous, remove closer to head, head section:
@@ -1265,7 +1280,7 @@ impl<T> VecDeque<T> {
12651280
self.copy(0, 1, self.head - 1);
12661281
}
12671282

1268-
self.head = self.wrap_index(self.head - 1);
1283+
self.head = self.wrap_sub(self.head, 1);
12691284
},
12701285
(false, true, false) => unsafe {
12711286
// discontiguous, remove closer to tail, head section:
@@ -1286,7 +1301,7 @@ impl<T> VecDeque<T> {
12861301
// move elements from tail to end forward, excluding the last one
12871302
self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);
12881303

1289-
self.tail = self.wrap_index(self.tail + 1);
1304+
self.tail = self.wrap_add(self.tail, 1);
12901305
}
12911306
}
12921307

@@ -1354,7 +1369,7 @@ impl<T> VecDeque<T> {
13541369
}
13551370

13561371
// Cleanup where the ends of the buffers are
1357-
self.head = self.wrap_index(self.head - other_len);
1372+
self.head = self.wrap_sub(self.head, other_len);
13581373
other.head = other.wrap_index(other_len);
13591374

13601375
other
@@ -1429,7 +1444,7 @@ fn wrap_index(index: usize, size: usize) -> usize {
14291444
#[inline]
14301445
fn count(tail: usize, head: usize, size: usize) -> usize {
14311446
// size is always a power of 2
1432-
(head - tail) & (size - 1)
1447+
(head.wrapping_sub(tail)) & (size - 1)
14331448
}
14341449

14351450
/// `VecDeque` iterator.
@@ -1461,7 +1476,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
14611476
return None;
14621477
}
14631478
let tail = self.tail;
1464-
self.tail = wrap_index(self.tail + 1, self.ring.len());
1479+
self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len());
14651480
unsafe { Some(self.ring.get_unchecked(tail)) }
14661481
}
14671482

@@ -1479,7 +1494,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
14791494
if self.tail == self.head {
14801495
return None;
14811496
}
1482-
self.head = wrap_index(self.head - 1, self.ring.len());
1497+
self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());
14831498
unsafe { Some(self.ring.get_unchecked(self.head)) }
14841499
}
14851500
}
@@ -1500,7 +1515,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
15001515
if j >= self.indexable() {
15011516
None
15021517
} else {
1503-
let idx = wrap_index(self.tail + j, self.ring.len());
1518+
let idx = wrap_index(self.tail.wrapping_add(j), self.ring.len());
15041519
unsafe { Some(self.ring.get_unchecked(idx)) }
15051520
}
15061521
}
@@ -1524,7 +1539,7 @@ impl<'a, T> Iterator for IterMut<'a, T> {
15241539
return None;
15251540
}
15261541
let tail = self.tail;
1527-
self.tail = wrap_index(self.tail + 1, self.ring.len());
1542+
self.tail = wrap_index(self.tail.wrapping_add(1), self.ring.len());
15281543

15291544
unsafe {
15301545
let elem = self.ring.get_unchecked_mut(tail);
@@ -1546,7 +1561,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
15461561
if self.tail == self.head {
15471562
return None;
15481563
}
1549-
self.head = wrap_index(self.head - 1, self.ring.len());
1564+
self.head = wrap_index(self.head.wrapping_sub(1), self.ring.len());
15501565

15511566
unsafe {
15521567
let elem = self.ring.get_unchecked_mut(self.head);

0 commit comments

Comments
 (0)