Skip to content

Commit fe08fb7

Browse files
committed
Auto merge of #74510 - LukasKalbertodt:fix-range-from-index-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).
2 parents 037d8e7 + 0d64b01 commit fe08fb7

File tree

3 files changed

+23
-10
lines changed

3 files changed

+23
-10
lines changed

Diff for: src/libcore/slice/mod.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -2974,8 +2974,15 @@ where
29742974
#[inline(never)]
29752975
#[cold]
29762976
#[track_caller]
2977-
fn slice_index_len_fail(index: usize, len: usize) -> ! {
2978-
panic!("index {} out of range for slice of length {}", index, len);
2977+
fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
2978+
panic!("range start index {} out of range for slice of length {}", index, len);
2979+
}
2980+
2981+
#[inline(never)]
2982+
#[cold]
2983+
#[track_caller]
2984+
fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
2985+
panic!("range end index {} out of range for slice of length {}", index, len);
29792986
}
29802987

29812988
#[inline(never)]
@@ -3160,7 +3167,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
31603167
if self.start > self.end {
31613168
slice_index_order_fail(self.start, self.end);
31623169
} else if self.end > slice.len() {
3163-
slice_index_len_fail(self.end, slice.len());
3170+
slice_end_index_len_fail(self.end, slice.len());
31643171
}
31653172
unsafe { &*self.get_unchecked(slice) }
31663173
}
@@ -3170,7 +3177,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
31703177
if self.start > self.end {
31713178
slice_index_order_fail(self.start, self.end);
31723179
} else if self.end > slice.len() {
3173-
slice_index_len_fail(self.end, slice.len());
3180+
slice_end_index_len_fail(self.end, slice.len());
31743181
}
31753182
unsafe { &mut *self.get_unchecked_mut(slice) }
31763183
}
@@ -3241,12 +3248,18 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
32413248

32423249
#[inline]
32433250
fn index(self, slice: &[T]) -> &[T] {
3244-
(self.start..slice.len()).index(slice)
3251+
if self.start > slice.len() {
3252+
slice_start_index_len_fail(self.start, slice.len());
3253+
}
3254+
unsafe { &*self.get_unchecked(slice) }
32453255
}
32463256

32473257
#[inline]
32483258
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
3249-
(self.start..slice.len()).index_mut(slice)
3259+
if self.start > slice.len() {
3260+
slice_start_index_len_fail(self.start, slice.len());
3261+
}
3262+
unsafe { &mut *self.get_unchecked_mut(slice) }
32503263
}
32513264
}
32523265

Diff for: src/libcore/tests/slice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1088,7 +1088,7 @@ mod slice_index {
10881088

10891089
good: data[6..] == [];
10901090
bad: data[7..];
1091-
message: "but ends at"; // perhaps not ideal
1091+
message: "out of range";
10921092
}
10931093

10941094
in mod rangeto_len {

Diff for: src/test/codegen/issue-69101-bounds-check.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// CHECK-LABEL: @already_sliced_no_bounds_check
1313
#[no_mangle]
1414
pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
15-
// CHECK: slice_index_len_fail
15+
// CHECK: slice_end_index_len_fail
1616
// CHECK-NOT: panic_bounds_check
1717
let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
1818
for i in 0..1024 {
@@ -23,7 +23,7 @@ pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
2323
// CHECK-LABEL: @already_sliced_no_bounds_check_exact
2424
#[no_mangle]
2525
pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
26-
// CHECK: slice_index_len_fail
26+
// CHECK: slice_end_index_len_fail
2727
// CHECK-NOT: panic_bounds_check
2828
let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
2929
for i in 0..1024 {
@@ -35,7 +35,7 @@ pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
3535
// CHECK-LABEL: @already_sliced_bounds_check
3636
#[no_mangle]
3737
pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
38-
// CHECK: slice_index_len_fail
38+
// CHECK: slice_end_index_len_fail
3939
// CHECK: panic_bounds_check
4040
let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
4141
for i in 0..1024 {

0 commit comments

Comments
 (0)