Skip to content

Commit

Permalink
Rollup merge of rust-lang#74510 - LukasKalbertodt:fix-range-from-inde…
Browse files Browse the repository at this point in the history
…x-panic, r=hanna-kruppe

Fix panic message when `RangeFrom` index is out of bounds

Before, the `Range` method was called with `end = slice.len()`. Unfortunately, because `Range::index` first checks the order of the indices (start has to be smaller than end), an out of bounds index leads to `core::slice::slice_index_order_fail` being called. This prints the message 'slice index starts at 27 but ends at 10', which is worse than 'index 27 out of range for slice of length 10'. This is not only useful to normal users reading panic messages, but also for people inspecting assembly and being confused by `slice_index_order_fail` calls.

You can see the produced assembly [here](https://rust.godbolt.org/z/GzMGWf) and try on Playground [here](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=aada5996b2f3848075a6d02cf4055743). (By the way. this is only about which panic function is called; I'm pretty sure it does not improve anything about performance).
  • Loading branch information
Manishearth authored Jul 19, 2020
2 parents 59617e4 + ea74e7d commit 89b814c
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
25 changes: 19 additions & 6 deletions src/libcore/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2974,8 +2974,15 @@ where
#[inline(never)]
#[cold]
#[track_caller]
fn slice_index_len_fail(index: usize, len: usize) -> ! {
panic!("index {} out of range for slice of length {}", index, len);
fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
panic!("range start index {} out of range for slice of length {}", index, len);
}

#[inline(never)]
#[cold]
#[track_caller]
fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
panic!("range end index {} out of range for slice of length {}", index, len);
}

#[inline(never)]
Expand Down Expand Up @@ -3160,7 +3167,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
if self.start > self.end {
slice_index_order_fail(self.start, self.end);
} else if self.end > slice.len() {
slice_index_len_fail(self.end, slice.len());
slice_end_index_len_fail(self.end, slice.len());
}
unsafe { &*self.get_unchecked(slice) }
}
Expand All @@ -3170,7 +3177,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
if self.start > self.end {
slice_index_order_fail(self.start, self.end);
} else if self.end > slice.len() {
slice_index_len_fail(self.end, slice.len());
slice_end_index_len_fail(self.end, slice.len());
}
unsafe { &mut *self.get_unchecked_mut(slice) }
}
Expand Down Expand Up @@ -3241,12 +3248,18 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {

#[inline]
fn index(self, slice: &[T]) -> &[T] {
(self.start..slice.len()).index(slice)
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
}
unsafe { &*self.get_unchecked(slice) }
}

#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
(self.start..slice.len()).index_mut(slice)
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
}
unsafe { &mut *self.get_unchecked_mut(slice) }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libcore/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ mod slice_index {

good: data[6..] == [];
bad: data[7..];
message: "but ends at"; // perhaps not ideal
message: "out of range";
}

in mod rangeto_len {
Expand Down

0 comments on commit 89b814c

Please sign in to comment.