diff --git a/library/alloctests/tests/str.rs b/library/alloctests/tests/str.rs index 52cc8afeee903..c0bcdb8500af6 100644 --- a/library/alloctests/tests/str.rs +++ b/library/alloctests/tests/str.rs @@ -612,14 +612,14 @@ mod slice_index { data: "abcdef"; good: data[4..4] == ""; bad: data[4..3]; - message: "begin > end (4 > 3)"; + message: "byte range starts at 4 but ends at 3"; } in mod rangeinclusive_neg_width { data: "abcdef"; good: data[4..=3] == ""; bad: data[4..=2]; - message: "begin > end (4 > 3)"; + message: "byte range starts at 4 but ends at 3"; } } @@ -659,49 +659,49 @@ mod slice_index { data: super::DATA; bad: data[super::BAD_START..super::GOOD_END]; message: - "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5 of string)"; } in mod range_2 { data: super::DATA; bad: data[super::GOOD_START..super::BAD_END]; message: - "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7 of string)"; } in mod rangefrom { data: super::DATA; bad: data[super::BAD_START..]; message: - "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5 of string)"; } in mod rangeto { data: super::DATA; bad: data[..super::BAD_END]; message: - "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7 of string)"; } in mod rangeinclusive_1 { data: super::DATA; bad: data[super::BAD_START..=super::GOOD_END_INCL]; message: - "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; + "start byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5 of string)"; } in mod rangeinclusive_2 { data: super::DATA; bad: data[super::GOOD_START..=super::BAD_END_INCL]; message: - "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7 of string)"; } in mod rangetoinclusive { data: super::DATA; bad: data[..=super::BAD_END_INCL]; message: - "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; + "end byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7 of string)"; } } } @@ -716,18 +716,10 @@ mod slice_index { // check the panic includes the prefix of the sliced string #[test] - #[should_panic( - expected = "end byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet" - )] + #[should_panic(expected = "end byte index 1024 is out of bounds for string of length 416")] fn test_slice_fail_truncated_1() { let _ = &LOREM_PARAGRAPH[..1024]; } - // check the truncation in the panic message - #[test] - #[should_panic(expected = "luctus, im`[...]")] - fn test_slice_fail_truncated_2() { - let _ = &LOREM_PARAGRAPH[..1024]; - } } #[test] diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 959407b753487..18310cf98918d 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -100,6 +100,13 @@ impl fmt::Display for AllocError { /// A memory block which is [*currently allocated*] may be passed to /// any method of the allocator that accepts such an argument. /// +/// Additionally, any memory block returned by the allocator must +/// satisfy the allocation invariants described in `core::ptr`. +/// In particular, if a block has base address `p` and size `n`, +/// then `p as usize + n <= usize::MAX` must hold. +/// +/// This ensures that pointer arithmetic within the allocation +/// (for example, `ptr.add(len)`) cannot overflow the address space. /// [*currently allocated*]: #currently-allocated-memory #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index ca2a4333eda52..20f85b5ca9cd8 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -2,6 +2,7 @@ use crate::async_iter::AsyncIterator; use crate::cell::UnsafeCell; use crate::fmt; use crate::future::Future; +use crate::marker::PointeeSized; use crate::ops::{Deref, DerefMut}; use crate::pin::Pin; use crate::ptr::{NonNull, Unique}; @@ -178,17 +179,17 @@ pub struct AssertUnwindSafe(#[stable(feature = "catch_unwind", since = "1.9.0 // * Our custom AssertUnwindSafe wrapper is indeed unwind safe #[stable(feature = "catch_unwind", since = "1.9.0")] -impl !UnwindSafe for &mut T {} +impl !UnwindSafe for &mut T {} #[stable(feature = "catch_unwind", since = "1.9.0")] -impl UnwindSafe for &T {} +impl UnwindSafe for &T {} #[stable(feature = "catch_unwind", since = "1.9.0")] -impl UnwindSafe for *const T {} +impl UnwindSafe for *const T {} #[stable(feature = "catch_unwind", since = "1.9.0")] -impl UnwindSafe for *mut T {} +impl UnwindSafe for *mut T {} #[unstable(feature = "ptr_internals", issue = "none")] -impl UnwindSafe for Unique {} +impl UnwindSafe for Unique {} #[stable(feature = "nonnull", since = "1.25.0")] -impl UnwindSafe for NonNull {} +impl UnwindSafe for NonNull {} #[stable(feature = "catch_unwind", since = "1.9.0")] impl UnwindSafe for AssertUnwindSafe {} diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 98354643aa405..0d52bfb8c9aa4 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -81,25 +81,21 @@ const fn slice_error_fail_ct(_: &str, _: usize, _: usize) -> ! { #[track_caller] fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { - const MAX_DISPLAY_LENGTH: usize = 256; - let trunc_len = s.floor_char_boundary(MAX_DISPLAY_LENGTH); - let s_trunc = &s[..trunc_len]; - let ellipsis = if trunc_len < s.len() { "[...]" } else { "" }; let len = s.len(); // 1. begin is OOB. if begin > len { - panic!("start byte index {begin} is out of bounds of `{s_trunc}`{ellipsis}"); + panic!("start byte index {begin} is out of bounds for string of length {len}"); } // 2. end is OOB. if end > len { - panic!("end byte index {end} is out of bounds of `{s_trunc}`{ellipsis}"); + panic!("end byte index {end} is out of bounds for string of length {len}"); } // 3. range is backwards. if begin > end { - panic!("begin > end ({begin} > {end}) when slicing `{s_trunc}`{ellipsis}") + panic!("byte range starts at {begin} but ends at {end}"); } // 4. begin is inside a character. @@ -109,7 +105,7 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { let range = floor..ceil; let ch = s[floor..ceil].chars().next().unwrap(); panic!( - "start byte index {begin} is not a char boundary; it is inside {ch:?} (bytes {range:?}) of `{s_trunc}`{ellipsis}" + "start byte index {begin} is not a char boundary; it is inside {ch:?} (bytes {range:?} of string)" ) } @@ -120,7 +116,7 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { let range = floor..ceil; let ch = s[floor..ceil].chars().next().unwrap(); panic!( - "end byte index {end} is not a char boundary; it is inside {ch:?} (bytes {range:?}) of `{s_trunc}`{ellipsis}" + "end byte index {end} is not a char boundary; it is inside {ch:?} (bytes {range:?} of string)" ) } @@ -128,7 +124,7 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { // This test cannot be combined with 2. above because for cases like // `"abcαβγ"[4..9]` the error is that 4 is inside 'α', not that 9 is OOB. debug_assert_eq!(end, len); - panic!("end byte index {end} is out of bounds of `{s_trunc}`{ellipsis}"); + panic!("end byte index {end} is out of bounds for string of length {len}"); } impl str { diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs index 7214918db6c39..a0978c3dafb48 100644 --- a/library/core/src/wtf8.rs +++ b/library/core/src/wtf8.rs @@ -484,11 +484,22 @@ unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 { } } -/// Copied from core::str::raw::slice_error_fail #[inline(never)] fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! { - assert!(begin <= end); - panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary"); + let len = s.len(); + if begin > len { + panic!("start byte index {begin} is out of bounds for string of length {len}"); + } + if end > len { + panic!("end byte index {end} is out of bounds for string of length {len}"); + } + if begin > end { + panic!("byte range starts at {begin} but ends at {end}"); + } + if !s.is_code_point_boundary(begin) { + panic!("byte index {begin} is not a code point boundary"); + } + panic!("byte index {end} is not a code point boundary"); } /// Iterator for the code points of a WTF-8 string. diff --git a/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr b/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr index aee60c94f106e..e07f356488276 100644 --- a/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr +++ b/tests/ui/intrinsics/const-eval-select-backtrace-std.run.stderr @@ -1,4 +1,4 @@ thread 'main' ($TID) panicked at $DIR/const-eval-select-backtrace-std.rs:6:8: -start byte index 1 is out of bounds of `` +start byte index 1 is out of bounds for string of length 0 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace