diff options
Diffstat (limited to '')
-rw-r--r-- | library/alloc/tests/boxed.rs | 41 | ||||
-rw-r--r-- | library/alloc/tests/fmt.rs | 13 | ||||
-rw-r--r-- | library/alloc/tests/lib.rs | 2 | ||||
-rw-r--r-- | library/alloc/tests/str.rs | 38 | ||||
-rw-r--r-- | library/alloc/tests/vec.rs | 3 | ||||
-rw-r--r-- | library/alloc/tests/vec_deque.rs | 21 |
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); +} |