Skip to content

Commit

Permalink
Avoid latent (harmless) overflow in core::slice.
Browse files Browse the repository at this point in the history
This overflow does not cause any problems; it just causes errors to be
signalled when compiling with `-C debug-assertions`.

Fix #24997
  • Loading branch information
pnkfelix committed May 4, 2015
1 parent f9ecc6e commit 42cb2de
Showing 1 changed file with 24 additions and 6 deletions.
30 changes: 24 additions & 6 deletions src/libcore/slice.rs
Expand Up @@ -631,8 +631,14 @@ fn size_from_ptr<T>(_: *const T) -> usize {
}


// Use macro to be generic over const/mut
macro_rules! slice_offset {
// Use macros to be generic over const/mut
//
// They require non-negative `$by` because otherwise the expression
// `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and
// thus trigger a panic when overflow checks are on).

// Use this to do `$ptr + $by`, where `$by` is non-negative.
macro_rules! slice_add_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
Expand All @@ -643,6 +649,18 @@ macro_rules! slice_offset {
}};
}

// Use this to do `$ptr - $by`, where `$by` is non-negative.
macro_rules! slice_sub_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
transmute(ptr as usize - $by)
} else {
ptr.offset(-$by)
}
}};
}

macro_rules! slice_ref {
($ptr:expr) => {{
let ptr = $ptr;
Expand Down Expand Up @@ -672,7 +690,7 @@ macro_rules! iterator {
None
} else {
let old = self.ptr;
self.ptr = slice_offset!(self.ptr, 1);
self.ptr = slice_add_offset!(self.ptr, 1);
Some(slice_ref!(old))
}
}
Expand Down Expand Up @@ -714,7 +732,7 @@ macro_rules! iterator {
if self.end == self.ptr {
None
} else {
self.end = slice_offset!(self.end, -1);
self.end = slice_sub_offset!(self.end, 1);
Some(slice_ref!(self.end))
}
}
Expand Down Expand Up @@ -816,7 +834,7 @@ impl<'a, T> Iter<'a, T> {
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
match self.as_slice().get(n) {
Some(elem_ref) => unsafe {
self.ptr = slice_offset!(elem_ref as *const _, 1);
self.ptr = slice_add_offset!(elem_ref as *const _, 1);
Some(slice_ref!(elem_ref))
},
None => {
Expand Down Expand Up @@ -959,7 +977,7 @@ impl<'a, T> IterMut<'a, T> {
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
Some(elem_ref) => unsafe {
self.ptr = slice_offset!(elem_ref as *mut _, 1);
self.ptr = slice_add_offset!(elem_ref as *mut _, 1);
Some(slice_ref!(elem_ref))
},
None => {
Expand Down

0 comments on commit 42cb2de

Please sign in to comment.