Auto merge of #32064 - bluss:str-slice-panic, r=alexcrichton
Fix panic on string slicing error to truncate the string The string may be arbitrarily long, but we want to limit the panic message to a reasonable length. Truncate the string if it is too long (simply to char boundary). Also add details to the start <= end message. I think it's ok to flesh out the code here, since it's in a cold function. Fixes #32063
This commit is contained in:
commit
6eb81a1f3b
2 changed files with 41 additions and 3 deletions
|
@ -346,6 +346,26 @@ fn test_slice_fail() {
|
||||||
&"中华Việt Nam"[0..2];
|
&"中华Việt Nam"[0..2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LOREM_PARAGRAPH: &'static str = "\
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
|
||||||
|
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
|
||||||
|
eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
|
||||||
|
sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
|
||||||
|
tempus vel, gravida nec quam.";
|
||||||
|
|
||||||
|
// check the panic includes the prefix of the sliced string
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected="Lorem ipsum dolor sit amet")]
|
||||||
|
fn test_slice_fail_truncated_1() {
|
||||||
|
&LOREM_PARAGRAPH[..1024];
|
||||||
|
}
|
||||||
|
// check the truncation in the panic message
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected="luctus, im`[...] do not lie on character boundary")]
|
||||||
|
fn test_slice_fail_truncated_2() {
|
||||||
|
&LOREM_PARAGRAPH[..1024];
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slice_from() {
|
fn test_slice_from() {
|
||||||
assert_eq!(&"abcd"[0..], "abcd");
|
assert_eq!(&"abcd"[0..], "abcd");
|
||||||
|
|
|
@ -1645,12 +1645,30 @@ pub trait StrExt {
|
||||||
fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
|
fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// truncate `&str` to length at most equal to `max`
|
||||||
|
// return `true` if it were truncated, and the new str.
|
||||||
|
fn truncate_to_char_boundary(s: &str, mut max: usize) -> (bool, &str) {
|
||||||
|
if max >= s.len() {
|
||||||
|
(false, s)
|
||||||
|
} else {
|
||||||
|
while !s.is_char_boundary(max) {
|
||||||
|
max -= 1;
|
||||||
|
}
|
||||||
|
(true, &s[..max])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
#[cold]
|
#[cold]
|
||||||
fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
|
fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
|
||||||
assert!(begin <= end);
|
const MAX_DISPLAY_LENGTH: usize = 256;
|
||||||
panic!("index {} and/or {} in `{}` do not lie on character boundary",
|
let (truncated, s) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH);
|
||||||
begin, end, s);
|
let ellipsis = if truncated { "[...]" } else { "" };
|
||||||
|
|
||||||
|
assert!(begin <= end, "begin <= end ({} <= {}) when slicing `{}`{}",
|
||||||
|
begin, end, s, ellipsis);
|
||||||
|
panic!("index {} and/or {} in `{}`{} do not lie on character boundary",
|
||||||
|
begin, end, s, ellipsis);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue