Rollup merge of #76662 - RalfJung:lib-test-miri, r=Mark-Simulacrum
Fix liballoc test suite for Miri Mostly, fix the regression introduced by https://github.com/rust-lang/rust/pull/75207 that caused slices (i.e., references) to be created to invalid memory or memory that has aliasing pointers that we want to keep valid. @dylni this changes the type of `check_range` to only require the length, not the full reference to the slice, which indeed is all the information this function requires. Also reduce the size of a test introduced in https://github.com/rust-lang/rust/pull/70793 to make it not take 3 minutes in Miri. This makes https://github.com/RalfJung/miri-test-libstd work again.
This commit is contained in:
commit
9d0a265b6c
@ -1089,11 +1089,7 @@ fn range_tail_head<R>(&self, range: R) -> (usize, usize)
|
|||||||
where
|
where
|
||||||
R: RangeBounds<usize>,
|
R: RangeBounds<usize>,
|
||||||
{
|
{
|
||||||
// SAFETY: This buffer is only used to check the range. It might be partially
|
let Range { start, end } = slice::check_range(self.len(), range);
|
||||||
// uninitialized, but `check_range` needs a contiguous slice.
|
|
||||||
// https://github.com/rust-lang/rust/pull/75207#discussion_r471193682
|
|
||||||
let buffer = unsafe { slice::from_raw_parts(self.ptr(), self.len()) };
|
|
||||||
let Range { start, end } = buffer.check_range(range);
|
|
||||||
let tail = self.wrap_add(self.tail, start);
|
let tail = self.wrap_add(self.tail, start);
|
||||||
let head = self.wrap_add(self.tail, end);
|
let head = self.wrap_add(self.tail, end);
|
||||||
(tail, head)
|
(tail, head)
|
||||||
|
@ -91,6 +91,8 @@
|
|||||||
use crate::boxed::Box;
|
use crate::boxed::Box;
|
||||||
use crate::vec::Vec;
|
use crate::vec::Vec;
|
||||||
|
|
||||||
|
#[unstable(feature = "slice_check_range", issue = "76393")]
|
||||||
|
pub use core::slice::check_range;
|
||||||
#[unstable(feature = "array_chunks", issue = "74985")]
|
#[unstable(feature = "array_chunks", issue = "74985")]
|
||||||
pub use core::slice::ArrayChunks;
|
pub use core::slice::ArrayChunks;
|
||||||
#[unstable(feature = "array_chunks", issue = "74985")]
|
#[unstable(feature = "array_chunks", issue = "74985")]
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
use core::ops::Bound::{Excluded, Included, Unbounded};
|
use core::ops::Bound::{Excluded, Included, Unbounded};
|
||||||
use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
|
use core::ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
use core::slice;
|
||||||
use core::str::{lossy, pattern::Pattern};
|
use core::str::{lossy, pattern::Pattern};
|
||||||
|
|
||||||
use crate::borrow::{Cow, ToOwned};
|
use crate::borrow::{Cow, ToOwned};
|
||||||
@ -1506,7 +1507,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_>
|
|||||||
// of the vector version. The data is just plain bytes.
|
// of the vector version. The data is just plain bytes.
|
||||||
// Because the range removal happens in Drop, if the Drain iterator is leaked,
|
// Because the range removal happens in Drop, if the Drain iterator is leaked,
|
||||||
// the removal will not happen.
|
// the removal will not happen.
|
||||||
let Range { start, end } = self.as_bytes().check_range(range);
|
let Range { start, end } = slice::check_range(self.len(), range);
|
||||||
assert!(self.is_char_boundary(start));
|
assert!(self.is_char_boundary(start));
|
||||||
assert!(self.is_char_boundary(end));
|
assert!(self.is_char_boundary(end));
|
||||||
|
|
||||||
|
@ -1312,7 +1312,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
|
|||||||
// the hole, and the vector length is restored to the new length.
|
// the hole, and the vector length is restored to the new length.
|
||||||
//
|
//
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
let Range { start, end } = self.check_range(range);
|
let Range { start, end } = slice::check_range(len, range);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// set self.vec length's to start, to be safe in case Drain is leaked
|
// set self.vec length's to start, to be safe in case Drain is leaked
|
||||||
|
@ -919,7 +919,7 @@ fn test_from_iter_partially_drained_in_place_specialization() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_from_iter_specialization_with_iterator_adapters() {
|
fn test_from_iter_specialization_with_iterator_adapters() {
|
||||||
fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
|
fn assert_in_place_trait<T: InPlaceIterable>(_: &T) {};
|
||||||
let src: Vec<usize> = vec![0usize; 65535];
|
let src: Vec<usize> = vec![0usize; 256];
|
||||||
let srcptr = src.as_ptr();
|
let srcptr = src.as_ptr();
|
||||||
let iter = src
|
let iter = src
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Indexing implementations for `[T]`.
|
//! Indexing implementations for `[T]`.
|
||||||
|
|
||||||
use crate::ops;
|
use crate::ops::{self, Bound, Range, RangeBounds};
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -62,6 +62,79 @@ pub(super) fn slice_end_index_overflow_fail() -> ! {
|
|||||||
panic!("attempted to index slice up to maximum usize");
|
panic!("attempted to index slice up to maximum usize");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs bounds-checking of the given range.
|
||||||
|
/// The returned [`Range`] is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`]
|
||||||
|
/// for slices of the given length.
|
||||||
|
///
|
||||||
|
/// [`get_unchecked`]: ../../std/primitive.slice.html#method.get_unchecked
|
||||||
|
/// [`get_unchecked_mut`]: ../../std/primitive.slice.html#method.get_unchecked_mut
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the range is out of bounds.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(slice_check_range)]
|
||||||
|
/// use std::slice;
|
||||||
|
///
|
||||||
|
/// let v = [10, 40, 30];
|
||||||
|
/// assert_eq!(1..2, slice::check_range(v.len(), 1..2));
|
||||||
|
/// assert_eq!(0..2, slice::check_range(v.len(), ..2));
|
||||||
|
/// assert_eq!(1..3, slice::check_range(v.len(), 1..));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Panics when [`Index::index`] would panic:
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// #![feature(slice_check_range)]
|
||||||
|
///
|
||||||
|
/// std::slice::check_range(3, 2..1);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// #![feature(slice_check_range)]
|
||||||
|
///
|
||||||
|
/// std::slice::check_range(3, 1..4);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```should_panic
|
||||||
|
/// #![feature(slice_check_range)]
|
||||||
|
///
|
||||||
|
/// std::slice::check_range(3, 1..=usize::MAX);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`Index::index`]: ops::Index::index
|
||||||
|
#[track_caller]
|
||||||
|
#[unstable(feature = "slice_check_range", issue = "76393")]
|
||||||
|
pub fn check_range<R: RangeBounds<usize>>(len: usize, range: R) -> Range<usize> {
|
||||||
|
let start = match range.start_bound() {
|
||||||
|
Bound::Included(&start) => start,
|
||||||
|
Bound::Excluded(start) => {
|
||||||
|
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
|
||||||
|
}
|
||||||
|
Bound::Unbounded => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let end = match range.end_bound() {
|
||||||
|
Bound::Included(end) => {
|
||||||
|
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
|
||||||
|
}
|
||||||
|
Bound::Excluded(&end) => end,
|
||||||
|
Bound::Unbounded => len,
|
||||||
|
};
|
||||||
|
|
||||||
|
if start > end {
|
||||||
|
slice_index_order_fail(start, end);
|
||||||
|
}
|
||||||
|
if end > len {
|
||||||
|
slice_end_index_len_fail(end, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
Range { start, end }
|
||||||
|
}
|
||||||
|
|
||||||
mod private_slice_index {
|
mod private_slice_index {
|
||||||
use super::ops;
|
use super::ops;
|
||||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
use crate::intrinsics::assume;
|
use crate::intrinsics::assume;
|
||||||
use crate::marker::{self, Copy};
|
use crate::marker::{self, Copy};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::ops::{Bound, FnMut, Range, RangeBounds};
|
use crate::ops::{FnMut, Range, RangeBounds};
|
||||||
use crate::option::Option;
|
use crate::option::Option;
|
||||||
use crate::option::Option::{None, Some};
|
use crate::option::Option::{None, Some};
|
||||||
use crate::ptr::{self, NonNull};
|
use crate::ptr::{self, NonNull};
|
||||||
@ -72,8 +72,8 @@
|
|||||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||||
pub use index::SliceIndex;
|
pub use index::SliceIndex;
|
||||||
|
|
||||||
use index::{slice_end_index_len_fail, slice_index_order_fail};
|
#[unstable(feature = "slice_check_range", issue = "76393")]
|
||||||
use index::{slice_end_index_overflow_fail, slice_start_index_overflow_fail};
|
pub use index::check_range;
|
||||||
|
|
||||||
#[lang = "slice"]
|
#[lang = "slice"]
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
@ -378,79 +378,6 @@ pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
|
|||||||
unsafe { &mut *index.get_unchecked_mut(self) }
|
unsafe { &mut *index.get_unchecked_mut(self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a range over this slice to [`Range`].
|
|
||||||
///
|
|
||||||
/// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
|
|
||||||
///
|
|
||||||
/// [`get_unchecked`]: #method.get_unchecked
|
|
||||||
/// [`get_unchecked_mut`]: #method.get_unchecked_mut
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if the range is out of bounds.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// #![feature(slice_check_range)]
|
|
||||||
///
|
|
||||||
/// let v = [10, 40, 30];
|
|
||||||
/// assert_eq!(1..2, v.check_range(1..2));
|
|
||||||
/// assert_eq!(0..2, v.check_range(..2));
|
|
||||||
/// assert_eq!(1..3, v.check_range(1..));
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Panics when [`Index::index`] would panic:
|
|
||||||
///
|
|
||||||
/// ```should_panic
|
|
||||||
/// #![feature(slice_check_range)]
|
|
||||||
///
|
|
||||||
/// [10, 40, 30].check_range(2..1);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ```should_panic
|
|
||||||
/// #![feature(slice_check_range)]
|
|
||||||
///
|
|
||||||
/// [10, 40, 30].check_range(1..4);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ```should_panic
|
|
||||||
/// #![feature(slice_check_range)]
|
|
||||||
///
|
|
||||||
/// [10, 40, 30].check_range(1..=usize::MAX);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// [`Index::index`]: crate::ops::Index::index
|
|
||||||
#[track_caller]
|
|
||||||
#[unstable(feature = "slice_check_range", issue = "76393")]
|
|
||||||
pub fn check_range<R: RangeBounds<usize>>(&self, range: R) -> Range<usize> {
|
|
||||||
let start = match range.start_bound() {
|
|
||||||
Bound::Included(&start) => start,
|
|
||||||
Bound::Excluded(start) => {
|
|
||||||
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
|
|
||||||
}
|
|
||||||
Bound::Unbounded => 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
let len = self.len();
|
|
||||||
let end = match range.end_bound() {
|
|
||||||
Bound::Included(end) => {
|
|
||||||
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
|
|
||||||
}
|
|
||||||
Bound::Excluded(&end) => end,
|
|
||||||
Bound::Unbounded => len,
|
|
||||||
};
|
|
||||||
|
|
||||||
if start > end {
|
|
||||||
slice_index_order_fail(start, end);
|
|
||||||
}
|
|
||||||
if end > len {
|
|
||||||
slice_end_index_len_fail(end, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
Range { start, end }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a raw pointer to the slice's buffer.
|
/// Returns a raw pointer to the slice's buffer.
|
||||||
///
|
///
|
||||||
/// The caller must ensure that the slice outlives the pointer this
|
/// The caller must ensure that the slice outlives the pointer this
|
||||||
@ -2794,7 +2721,7 @@ pub fn copy_within<R: RangeBounds<usize>>(&mut self, src: R, dest: usize)
|
|||||||
where
|
where
|
||||||
T: Copy,
|
T: Copy,
|
||||||
{
|
{
|
||||||
let Range { start: src_start, end: src_end } = self.check_range(src);
|
let Range { start: src_start, end: src_end } = check_range(self.len(), src);
|
||||||
let count = src_end - src_start;
|
let count = src_end - src_start;
|
||||||
assert!(dest <= self.len() - count, "dest is out of bounds");
|
assert!(dest <= self.len() - count, "dest is out of bounds");
|
||||||
// SAFETY: the conditions for `ptr::copy` have all been checked above,
|
// SAFETY: the conditions for `ptr::copy` have all been checked above,
|
||||||
|
Loading…
Reference in New Issue
Block a user