From 42cb2de1393b067f1078f0c8b55322620e6058ef Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 1 May 2015 01:00:48 +0200 Subject: [PATCH] Avoid latent (harmless) overflow in core::slice. This overflow does not cause any problems; it just causes errors to be signalled when compiling with `-C debug-assertions`. Fix #24997 --- src/libcore/slice.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 38e66c5a3d6a2..d99ea607e5db3 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -631,8 +631,14 @@ fn size_from_ptr(_: *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 { @@ -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; @@ -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)) } } @@ -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)) } } @@ -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 => { @@ -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 => {