Skip to content

Commit 808a08a

Browse files
committed
Add overflow checking for str::get with inclusive ranges
Fixes #42401
1 parent 18612b2 commit 808a08a

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

src/libcollections/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#![feature(rand)]
2323
#![feature(slice_rotate)]
2424
#![feature(splice)]
25+
#![feature(str_checked_slicing)]
2526
#![feature(str_escape)]
2627
#![feature(test)]
2728
#![feature(unboxed_closures)]

src/libcollections/tests/str.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,48 @@ fn test_slice_fail() {
358358
&"中华Việt Nam"[0..2];
359359
}
360360

361+
#[test]
362+
#[should_panic]
363+
fn test_str_slice_rangetoinclusive_max_panics() {
364+
&"hello"[...usize::max_value()];
365+
}
366+
367+
#[test]
368+
#[should_panic]
369+
fn test_str_slice_rangeinclusive_max_panics() {
370+
&"hello"[1...usize::max_value()];
371+
}
372+
373+
#[test]
374+
#[should_panic]
375+
fn test_str_slicemut_rangetoinclusive_max_panics() {
376+
let mut s = "hello".to_owned();
377+
let s: &mut str = &mut s;
378+
&mut s[...usize::max_value()];
379+
}
380+
381+
#[test]
382+
#[should_panic]
383+
fn test_str_slicemut_rangeinclusive_max_panics() {
384+
let mut s = "hello".to_owned();
385+
let s: &mut str = &mut s;
386+
&mut s[1...usize::max_value()];
387+
}
388+
389+
#[test]
390+
fn test_str_get_maxinclusive() {
391+
let mut s = "hello".to_owned();
392+
{
393+
let s: &str = &s;
394+
assert_eq!(s.get(...usize::max_value()), None);
395+
assert_eq!(s.get(1...usize::max_value()), None);
396+
}
397+
{
398+
let s: &mut str = &mut s;
399+
assert_eq!(s.get(...usize::max_value()), None);
400+
assert_eq!(s.get(1...usize::max_value()), None);
401+
}
402+
}
361403

362404
#[test]
363405
fn test_is_char_boundary() {

src/libcore/str/mod.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,11 +1918,19 @@ mod traits {
19181918
type Output = str;
19191919
#[inline]
19201920
fn get(self, slice: &str) -> Option<&Self::Output> {
1921-
(self.start..self.end+1).get(slice)
1921+
if let Some(end) = self.end.checked_add(1) {
1922+
(self.start..end).get(slice)
1923+
} else {
1924+
None
1925+
}
19221926
}
19231927
#[inline]
19241928
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1925-
(self.start..self.end+1).get_mut(slice)
1929+
if let Some(end) = self.end.checked_add(1) {
1930+
(self.start..end).get_mut(slice)
1931+
} else {
1932+
None
1933+
}
19261934
}
19271935
#[inline]
19281936
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
@@ -1953,15 +1961,15 @@ mod traits {
19531961
type Output = str;
19541962
#[inline]
19551963
fn get(self, slice: &str) -> Option<&Self::Output> {
1956-
if slice.is_char_boundary(self.end + 1) {
1964+
if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) {
19571965
Some(unsafe { self.get_unchecked(slice) })
19581966
} else {
19591967
None
19601968
}
19611969
}
19621970
#[inline]
19631971
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
1964-
if slice.is_char_boundary(self.end + 1) {
1972+
if self.end < usize::max_value() && slice.is_char_boundary(self.end + 1) {
19651973
Some(unsafe { self.get_unchecked_mut(slice) })
19661974
} else {
19671975
None

0 commit comments

Comments
 (0)