summaryrefslogtreecommitdiffstats
path: root/library/alloc/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/alloc/tests/boxed.rs41
-rw-r--r--library/alloc/tests/fmt.rs13
-rw-r--r--library/alloc/tests/lib.rs2
-rw-r--r--library/alloc/tests/str.rs38
-rw-r--r--library/alloc/tests/vec.rs3
-rw-r--r--library/alloc/tests/vec_deque.rs21
6 files changed, 94 insertions, 24 deletions
diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs
index 9e5123be9..af49826ff 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloc/tests/boxed.rs
@@ -102,8 +102,18 @@ unsafe impl const Allocator for ConstAllocator {
let new_ptr = self.allocate(new_layout)?;
if new_layout.size() > 0 {
- new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), old_layout.size());
- self.deallocate(ptr, old_layout);
+ // Safety: `new_ptr` is valid for writes and `ptr` for reads of
+ // `old_layout.size()`, because `new_layout.size() >=
+ // old_layout.size()` (which is an invariant that must be upheld by
+ // callers).
+ unsafe {
+ new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), old_layout.size());
+ }
+ // Safety: `ptr` is never used again is also an invariant which must
+ // be upheld by callers.
+ unsafe {
+ self.deallocate(ptr, old_layout);
+ }
}
Ok(new_ptr)
}
@@ -114,12 +124,21 @@ unsafe impl const Allocator for ConstAllocator {
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, AllocError> {
- let new_ptr = self.grow(ptr, old_layout, new_layout)?;
+ // Safety: Invariants of `grow_zeroed` and `grow` are the same, and must
+ // be enforced by callers.
+ let new_ptr = unsafe { self.grow(ptr, old_layout, new_layout)? };
if new_layout.size() > 0 {
let old_size = old_layout.size();
let new_size = new_layout.size();
let raw_ptr = new_ptr.as_mut_ptr();
- raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
+ // Safety:
+ // - `grow` returned Ok, so the returned pointer must be valid for
+ // `new_size` bytes
+ // - `new_size` must be larger than `old_size`, which is an
+ // invariant which must be upheld by callers.
+ unsafe {
+ raw_ptr.add(old_size).write_bytes(0, new_size - old_size);
+ }
}
Ok(new_ptr)
}
@@ -137,8 +156,18 @@ unsafe impl const Allocator for ConstAllocator {
let new_ptr = self.allocate(new_layout)?;
if new_layout.size() > 0 {
- new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), new_layout.size());
- self.deallocate(ptr, old_layout);
+ // Safety: `new_ptr` and `ptr` are valid for reads/writes of
+ // `new_layout.size()` because of the invariants of shrink, which
+ // include `new_layout.size()` being smaller than (or equal to)
+ // `old_layout.size()`.
+ unsafe {
+ new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), new_layout.size());
+ }
+ // Safety: `ptr` is never used again is also an invariant which must
+ // be upheld by callers.
+ unsafe {
+ self.deallocate(ptr, old_layout);
+ }
}
Ok(new_ptr)
}
diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs
index 5ee6db43f..04da95bbb 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloc/tests/fmt.rs
@@ -2,6 +2,7 @@
use std::cell::RefCell;
use std::fmt::{self, Write};
+use std::ptr;
#[test]
fn test_format() {
@@ -76,14 +77,14 @@ fn test_format_macro_interface() {
t!(format!("{}", "foo"), "foo");
t!(format!("{}", "foo".to_string()), "foo");
if cfg!(target_pointer_width = "32") {
- t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234");
- t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234");
+ t!(format!("{:#p}", ptr::invalid::<isize>(0x1234)), "0x00001234");
+ t!(format!("{:#p}", ptr::invalid_mut::<isize>(0x1234)), "0x00001234");
} else {
- t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234");
- t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234");
+ t!(format!("{:#p}", ptr::invalid::<isize>(0x1234)), "0x0000000000001234");
+ t!(format!("{:#p}", ptr::invalid_mut::<isize>(0x1234)), "0x0000000000001234");
}
- t!(format!("{:p}", 0x1234 as *const isize), "0x1234");
- t!(format!("{:p}", 0x1234 as *mut isize), "0x1234");
+ t!(format!("{:p}", ptr::invalid::<isize>(0x1234)), "0x1234");
+ t!(format!("{:p}", ptr::invalid_mut::<isize>(0x1234)), "0x1234");
t!(format!("{A:x}"), "aloha");
t!(format!("{B:X}"), "adios");
t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃");
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index ffc5ca7a5..d6d2b055b 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -47,6 +47,8 @@
#![feature(strict_provenance)]
#![feature(once_cell)]
#![feature(drain_keep_rest)]
+#![deny(fuzzy_provenance_casts)]
+#![deny(unsafe_op_in_unsafe_fn)]
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index e30329aa1..4d182be02 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1590,11 +1590,27 @@ fn test_bool_from_str() {
assert_eq!("not even a boolean".parse::<bool>().ok(), None);
}
-fn check_contains_all_substrings(s: &str) {
- assert!(s.contains(""));
- for i in 0..s.len() {
- for j in i + 1..=s.len() {
- assert!(s.contains(&s[i..j]));
+fn check_contains_all_substrings(haystack: &str) {
+ let mut modified_needle = String::new();
+
+ for i in 0..haystack.len() {
+ // check different haystack lengths since we special-case short haystacks.
+ let haystack = &haystack[0..i];
+ assert!(haystack.contains(""));
+ for j in 0..haystack.len() {
+ for k in j + 1..=haystack.len() {
+ let needle = &haystack[j..k];
+ assert!(haystack.contains(needle));
+ modified_needle.clear();
+ modified_needle.push_str(needle);
+ modified_needle.replace_range(0..1, "\0");
+ assert!(!haystack.contains(&modified_needle));
+
+ modified_needle.clear();
+ modified_needle.push_str(needle);
+ modified_needle.replace_range(needle.len() - 1..needle.len(), "\0");
+ assert!(!haystack.contains(&modified_needle));
+ }
}
}
}
@@ -1616,6 +1632,18 @@ fn strslice_issue_16878() {
}
#[test]
+fn strslice_issue_104726() {
+ // Edge-case in the simd_contains impl.
+ // The first and last byte are the same so it backtracks by one byte
+ // which aligns with the end of the string. Previously incorrect offset calculations
+ // lead to out-of-bounds slicing.
+ #[rustfmt::skip]
+ let needle = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaba";
+ let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
+ assert!(!haystack.contains(needle));
+}
+
+#[test]
#[cfg_attr(miri, ignore)] // Miri is too slow
fn test_strslice_contains() {
let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index e02711870..7ebed0d5c 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1089,7 +1089,8 @@ fn test_into_iter_drop_allocator() {
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
- System.deallocate(ptr, layout)
+ // Safety: Invariants passed to caller.
+ unsafe { System.deallocate(ptr, layout) }
}
}
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs
index 019d73c0b..d04de5a07 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloc/tests/vec_deque.rs
@@ -465,7 +465,6 @@ fn test_drain() {
for i in 6..9 {
d.push_front(i);
}
-
assert_eq!(d.drain(..).collect::<Vec<_>>(), [8, 7, 6, 0, 1, 2, 3, 4]);
assert!(d.is_empty());
}
@@ -1142,7 +1141,7 @@ fn test_reserve_exact_2() {
v.push_back(16);
v.reserve_exact(16);
- assert!(v.capacity() >= 48)
+ assert!(v.capacity() >= 33)
}
#[test]
@@ -1157,7 +1156,7 @@ fn test_try_reserve() {
// * overflow may trigger when adding `len` to `cap` (in number of elements)
// * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
- const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1;
+ const MAX_CAP: usize = isize::MAX as usize;
const MAX_USIZE: usize = usize::MAX;
{
@@ -1248,7 +1247,7 @@ fn test_try_reserve_exact() {
// This is exactly the same as test_try_reserve with the method changed.
// See that test for comments.
- const MAX_CAP: usize = (isize::MAX as usize + 1) / 2 - 1;
+ const MAX_CAP: usize = isize::MAX as usize;
const MAX_USIZE: usize = usize::MAX;
{
@@ -1391,7 +1390,8 @@ fn test_rotate_nop() {
#[test]
fn test_rotate_left_parts() {
- let mut v: VecDeque<_> = (1..=7).collect();
+ let mut v: VecDeque<_> = VecDeque::with_capacity(8);
+ v.extend(1..=7);
v.rotate_left(2);
assert_eq!(v.as_slices(), (&[3, 4, 5, 6, 7, 1][..], &[2][..]));
v.rotate_left(2);
@@ -1410,7 +1410,8 @@ fn test_rotate_left_parts() {
#[test]
fn test_rotate_right_parts() {
- let mut v: VecDeque<_> = (1..=7).collect();
+ let mut v: VecDeque<_> = VecDeque::with_capacity(8);
+ v.extend(1..=7);
v.rotate_right(2);
assert_eq!(v.as_slices(), (&[6, 7][..], &[1, 2, 3, 4, 5][..]));
v.rotate_right(2);
@@ -1727,3 +1728,11 @@ fn test_from_zero_sized_vec() {
let queue = VecDeque::from(v);
assert_eq!(queue.len(), 100);
}
+
+#[test]
+fn test_resize_keeps_reserved_space_from_item() {
+ let v = Vec::<i32>::with_capacity(1234);
+ let mut d = VecDeque::new();
+ d.resize(1, v);
+ assert_eq!(d[0].capacity(), 1234);
+}