Skip to content

Commit 42cb2de

Browse files
committed
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
1 parent f9ecc6e commit 42cb2de

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

src/libcore/slice.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -631,8 +631,14 @@ fn size_from_ptr<T>(_: *const T) -> usize {
631631
}
632632

633633

634-
// Use macro to be generic over const/mut
635-
macro_rules! slice_offset {
634+
// Use macros to be generic over const/mut
635+
//
636+
// They require non-negative `$by` because otherwise the expression
637+
// `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and
638+
// thus trigger a panic when overflow checks are on).
639+
640+
// Use this to do `$ptr + $by`, where `$by` is non-negative.
641+
macro_rules! slice_add_offset {
636642
($ptr:expr, $by:expr) => {{
637643
let ptr = $ptr;
638644
if size_from_ptr(ptr) == 0 {
@@ -643,6 +649,18 @@ macro_rules! slice_offset {
643649
}};
644650
}
645651

652+
// Use this to do `$ptr - $by`, where `$by` is non-negative.
653+
macro_rules! slice_sub_offset {
654+
($ptr:expr, $by:expr) => {{
655+
let ptr = $ptr;
656+
if size_from_ptr(ptr) == 0 {
657+
transmute(ptr as usize - $by)
658+
} else {
659+
ptr.offset(-$by)
660+
}
661+
}};
662+
}
663+
646664
macro_rules! slice_ref {
647665
($ptr:expr) => {{
648666
let ptr = $ptr;
@@ -672,7 +690,7 @@ macro_rules! iterator {
672690
None
673691
} else {
674692
let old = self.ptr;
675-
self.ptr = slice_offset!(self.ptr, 1);
693+
self.ptr = slice_add_offset!(self.ptr, 1);
676694
Some(slice_ref!(old))
677695
}
678696
}
@@ -714,7 +732,7 @@ macro_rules! iterator {
714732
if self.end == self.ptr {
715733
None
716734
} else {
717-
self.end = slice_offset!(self.end, -1);
735+
self.end = slice_sub_offset!(self.end, 1);
718736
Some(slice_ref!(self.end))
719737
}
720738
}
@@ -816,7 +834,7 @@ impl<'a, T> Iter<'a, T> {
816834
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
817835
match self.as_slice().get(n) {
818836
Some(elem_ref) => unsafe {
819-
self.ptr = slice_offset!(elem_ref as *const _, 1);
837+
self.ptr = slice_add_offset!(elem_ref as *const _, 1);
820838
Some(slice_ref!(elem_ref))
821839
},
822840
None => {
@@ -959,7 +977,7 @@ impl<'a, T> IterMut<'a, T> {
959977
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
960978
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
961979
Some(elem_ref) => unsafe {
962-
self.ptr = slice_offset!(elem_ref as *mut _, 1);
980+
self.ptr = slice_add_offset!(elem_ref as *mut _, 1);
963981
Some(slice_ref!(elem_ref))
964982
},
965983
None => {

0 commit comments

Comments
 (0)