|
| 1 | +diff --git a/library/alloc/src/collections/vec_deque.rs b/library/alloc/src/collections/vec_deque.rs |
| 2 | +index 253a3e9f2be..65cfe9a9b49 100644 |
| 3 | +--- a/library/alloc/src/collections/vec_deque.rs |
| 4 | ++++ b/library/alloc/src/collections/vec_deque.rs |
| 5 | +@@ -1089,11 +1089,7 @@ impl<T> VecDeque<T> { |
| 6 | + where |
| 7 | + R: RangeBounds<usize>, |
| 8 | + { |
| 9 | +- // SAFETY: This buffer is only used to check the range. It might be partially |
| 10 | +- // uninitialized, but `check_range` needs a contiguous slice. |
| 11 | +- // https://github.com/rust-lang/rust/pull/75207#discussion_r471193682 |
| 12 | +- let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) }; |
| 13 | +- let Range { start, end } = buffer.check_range(range); |
| 14 | ++ let Range { start, end } = slice::check_range(self.len(), range); |
| 15 | + let tail = self.wrap_add(self.tail, start); |
| 16 | + let head = self.wrap_add(self.tail, end); |
| 17 | + (tail, head) |
| 18 | +diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs |
| 19 | +index 677bfdd2349..55afdd94f44 100644 |
| 20 | +--- a/library/alloc/src/slice.rs |
| 21 | ++++ b/library/alloc/src/slice.rs |
| 22 | +@@ -91,6 +91,8 @@ use crate::borrow::ToOwned; |
| 23 | + use crate::boxed::Box; |
| 24 | + use crate::vec::Vec; |
| 25 | + |
| 26 | ++#[unstable(feature = "slice_check_range", issue = "76393")] |
| 27 | ++pub use core::slice::check_range; |
| 28 | + #[unstable(feature = "array_chunks", issue = "74985")] |
| 29 | + pub use core::slice::ArrayChunks; |
| 30 | + #[unstable(feature = "array_chunks", issue = "74985")] |
| 31 | +diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs |
| 32 | +index e1724bf3c9a..2b0ce5ede56 100644 |
| 33 | +--- a/library/alloc/src/string.rs |
| 34 | ++++ b/library/alloc/src/string.rs |
| 35 | +@@ -49,6 +49,7 @@ use core::iter::{FromIterator, FusedIterator}; |
| 36 | + use core::ops::Bound::{Excluded, Included, Unbounded}; |
| 37 | + use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds}; |
| 38 | + use core::ptr; |
| 39 | ++use core::slice; |
| 40 | + use core::str::{lossy, pattern::Pattern}; |
| 41 | + |
| 42 | + use crate::borrow::{Cow, ToOwned}; |
| 43 | +@@ -1506,7 +1507,7 @@ impl String { |
| 44 | + // of the vector version. The data is just plain bytes. |
| 45 | + // Because the range removal happens in Drop, if the Drain iterator is leaked, |
| 46 | + // the removal will not happen. |
| 47 | +- let Range { start, end } = self.as_bytes().check_range(range); |
| 48 | ++ let Range { start, end } = slice::check_range(self.len(), range); |
| 49 | + assert!(self.is_char_boundary(start)); |
| 50 | + assert!(self.is_char_boundary(end)); |
| 51 | + |
| 52 | +diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs |
| 53 | +index baa6c0919de..3d48a06fd24 100644 |
| 54 | +--- a/library/alloc/src/vec.rs |
| 55 | ++++ b/library/alloc/src/vec.rs |
| 56 | +@@ -1310,7 +1310,7 @@ impl<T> Vec<T> { |
| 57 | + // the hole, and the vector length is restored to the new length. |
| 58 | + // |
| 59 | + let len = self.len(); |
| 60 | +- let Range { start, end } = self.check_range(range); |
| 61 | ++ let Range { start, end } = slice::check_range(len, range); |
| 62 | + |
| 63 | + unsafe { |
| 64 | + // set self.vec length's to start, to be safe in case Drain is leaked |
| 65 | +diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs |
| 66 | +index 53b0d0a2718..f3e6eb62926 100644 |
| 67 | +--- a/library/alloc/tests/vec.rs |
| 68 | ++++ b/library/alloc/tests/vec.rs |
| 69 | +@@ -880,7 +880,7 @@ fn test_from_iter_partially_drained_in_place_specialization() { |
| 70 | + #[test] |
| 71 | + fn test_from_iter_specialization_with_iterator_adapters() { |
| 72 | + fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {}; |
| 73 | +- let src: Vec<usize> = vec![0usize; 65535]; |
| 74 | ++ let src: Vec<usize> = vec![0usize; if cfg!(miri) { 256 } else { 65535 }]; |
| 75 | + let srcptr = src.as_ptr(); |
| 76 | + let iter = src |
| 77 | + .into_iter() |
| 78 | +diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs |
| 79 | +index 4c027b23584..b4531f2d18c 100644 |
| 80 | +--- a/library/core/src/slice/mod.rs |
| 81 | ++++ b/library/core/src/slice/mod.rs |
| 82 | +@@ -354,79 +354,6 @@ impl<T> [T] { |
| 83 | + unsafe { &mut *index.get_unchecked_mut(self) } |
| 84 | + } |
| 85 | + |
| 86 | +- /// Converts a range over this slice to [`Range`]. |
| 87 | +- /// |
| 88 | +- /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]. |
| 89 | +- /// |
| 90 | +- /// [`get_unchecked`]: #method.get_unchecked |
| 91 | +- /// [`get_unchecked_mut`]: #method.get_unchecked_mut |
| 92 | +- /// |
| 93 | +- /// # Panics |
| 94 | +- /// |
| 95 | +- /// Panics if the range is out of bounds. |
| 96 | +- /// |
| 97 | +- /// # Examples |
| 98 | +- /// |
| 99 | +- /// ``` |
| 100 | +- /// #![feature(slice_check_range)] |
| 101 | +- /// |
| 102 | +- /// let v = [10, 40, 30]; |
| 103 | +- /// assert_eq!(1..2, v.check_range(1..2)); |
| 104 | +- /// assert_eq!(0..2, v.check_range(..2)); |
| 105 | +- /// assert_eq!(1..3, v.check_range(1..)); |
| 106 | +- /// ``` |
| 107 | +- /// |
| 108 | +- /// Panics when [`Index::index`] would panic: |
| 109 | +- /// |
| 110 | +- /// ```should_panic |
| 111 | +- /// #![feature(slice_check_range)] |
| 112 | +- /// |
| 113 | +- /// [10, 40, 30].check_range(2..1); |
| 114 | +- /// ``` |
| 115 | +- /// |
| 116 | +- /// ```should_panic |
| 117 | +- /// #![feature(slice_check_range)] |
| 118 | +- /// |
| 119 | +- /// [10, 40, 30].check_range(1..4); |
| 120 | +- /// ``` |
| 121 | +- /// |
| 122 | +- /// ```should_panic |
| 123 | +- /// #![feature(slice_check_range)] |
| 124 | +- /// |
| 125 | +- /// [10, 40, 30].check_range(1..=usize::MAX); |
| 126 | +- /// ``` |
| 127 | +- /// |
| 128 | +- /// [`Index::index`]: ops::Index::index |
| 129 | +- #[track_caller] |
| 130 | +- #[unstable(feature = "slice_check_range", issue = "76393")] |
| 131 | +- pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> { |
| 132 | +- let start = match range.start_bound() { |
| 133 | +- Bound::Included(&start) => start, |
| 134 | +- Bound::Excluded(start) => { |
| 135 | +- start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) |
| 136 | +- } |
| 137 | +- Bound::Unbounded => 0, |
| 138 | +- }; |
| 139 | +- |
| 140 | +- let len = self.len(); |
| 141 | +- let end = match range.end_bound() { |
| 142 | +- Bound::Included(end) => { |
| 143 | +- end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) |
| 144 | +- } |
| 145 | +- Bound::Excluded(&end) => end, |
| 146 | +- Bound::Unbounded => len, |
| 147 | +- }; |
| 148 | +- |
| 149 | +- if start > end { |
| 150 | +- slice_index_order_fail(start, end); |
| 151 | +- } |
| 152 | +- if end > len { |
| 153 | +- slice_end_index_len_fail(end, len); |
| 154 | +- } |
| 155 | +- |
| 156 | +- Range { start, end } |
| 157 | +- } |
| 158 | +- |
| 159 | + /// Returns a raw pointer to the slice's buffer. |
| 160 | + /// |
| 161 | + /// The caller must ensure that the slice outlives the pointer this |
| 162 | +@@ -2770,7 +2697,7 @@ impl<T> [T] { |
| 163 | + where |
| 164 | + T: Copy, |
| 165 | + { |
| 166 | +- let Range { start: src_start, end: src_end } = self.check_range(src); |
| 167 | ++ let Range { start: src_start, end: src_end } = check_range(self.len(), src); |
| 168 | + let count = src_end - src_start; |
| 169 | + assert!(dest <= self.len() - count, "dest is out of bounds"); |
| 170 | + // SAFETY: the conditions for `ptr::copy` have all been checked above, |
| 171 | +@@ -6660,6 +6587,79 @@ unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> { |
| 172 | + // Free functions |
| 173 | + // |
| 174 | + |
| 175 | ++/// Converts a range over this slice to [`Range`]. |
| 176 | ++/// |
| 177 | ++/// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]. |
| 178 | ++/// |
| 179 | ++/// [`get_unchecked`]: #method.get_unchecked |
| 180 | ++/// [`get_unchecked_mut`]: #method.get_unchecked_mut |
| 181 | ++/// |
| 182 | ++/// # Panics |
| 183 | ++/// |
| 184 | ++/// Panics if the range is out of bounds. |
| 185 | ++/// |
| 186 | ++/// # Examples |
| 187 | ++/// |
| 188 | ++/// ``` |
| 189 | ++/// #![feature(slice_check_range)] |
| 190 | ++/// use std::slice; |
| 191 | ++/// |
| 192 | ++/// let v = [10, 40, 30]; |
| 193 | ++/// assert_eq!(1..2, slice::check_range(v.len(), 1..2)); |
| 194 | ++/// assert_eq!(0..2, slice::check_range(v.len(), ..2)); |
| 195 | ++/// assert_eq!(1..3, slice::check_range(v.len(), 1..)); |
| 196 | ++/// ``` |
| 197 | ++/// |
| 198 | ++/// Panics when [`Index::index`] would panic: |
| 199 | ++/// |
| 200 | ++/// ```should_panic |
| 201 | ++/// #![feature(slice_check_range)] |
| 202 | ++/// |
| 203 | ++/// std::slice::check_range(3, 2..1); |
| 204 | ++/// ``` |
| 205 | ++/// |
| 206 | ++/// ```should_panic |
| 207 | ++/// #![feature(slice_check_range)] |
| 208 | ++/// |
| 209 | ++/// std::slice::check_range(3, 1..4); |
| 210 | ++/// ``` |
| 211 | ++/// |
| 212 | ++/// ```should_panic |
| 213 | ++/// #![feature(slice_check_range)] |
| 214 | ++/// |
| 215 | ++/// std::slice::check_range(3, 1..=usize::MAX); |
| 216 | ++/// ``` |
| 217 | ++/// |
| 218 | ++/// [`Index::index`]: ops::Index::index |
| 219 | ++#[track_caller] |
| 220 | ++#[unstable(feature = "slice_check_range", issue = "76393")] |
| 221 | ++pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> { |
| 222 | ++ let start = match range.start_bound() { |
| 223 | ++ Bound::Included(&start) => start, |
| 224 | ++ Bound::Excluded(start) => { |
| 225 | ++ start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail()) |
| 226 | ++ } |
| 227 | ++ Bound::Unbounded => 0, |
| 228 | ++ }; |
| 229 | ++ |
| 230 | ++ let end = match range.end_bound() { |
| 231 | ++ Bound::Included(end) => { |
| 232 | ++ end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail()) |
| 233 | ++ } |
| 234 | ++ Bound::Excluded(&end) => end, |
| 235 | ++ Bound::Unbounded => len, |
| 236 | ++ }; |
| 237 | ++ |
| 238 | ++ if start > end { |
| 239 | ++ slice_index_order_fail(start, end); |
| 240 | ++ } |
| 241 | ++ if end > len { |
| 242 | ++ slice_end_index_len_fail(end, len); |
| 243 | ++ } |
| 244 | ++ |
| 245 | ++ Range { start, end } |
| 246 | ++} |
| 247 | ++ |
| 248 | + /// Forms a slice from a pointer and a length. |
| 249 | + /// |
| 250 | + /// The `len` argument is the number of **elements**, not the number of bytes. |
0 commit comments