diff options
| author | bors <bors@rust-lang.org> | 2025-07-15 14:47:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-07-15 14:47:10 +0000 |
| commit | 3014e79f9c8d5510ea7b3a3b70d171d0948b1e96 (patch) | |
| tree | a98190833007bcd5ad9ad6d25dc4a3853d2ab7a4 /library/alloc/src/vec/mod.rs | |
| parent | e27f16a499074ba9a87f7f7641d9f64c572863bc (diff) | |
| parent | a74a28493a00900616d5e52cd85b8b6bae761935 (diff) | |
| download | rust-3014e79f9c8d5510ea7b3a3b70d171d0948b1e96.tar.gz rust-3014e79f9c8d5510ea7b3a3b70d171d0948b1e96.zip | |
Auto merge of #143877 - xizheyin:143813, r=scottmcm,saethlin
`std::vec`: Add UB check for `set_len`, `from_raw_parts_in`, and etc. Closes rust-lang/rust#143813 I noticed that `from_parts_in` do the similar things like `from_raw_parts_in`, so I add the UB check in the last commit. If it is not appropriate, I will remove it. And I fix a typo in the first commit. r? `@scottmcm`
Diffstat (limited to 'library/alloc/src/vec/mod.rs')
| -rw-r--r-- | library/alloc/src/vec/mod.rs | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1df6ab672ea..9856e9c18ec 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -64,7 +64,7 @@ use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::ops::{self, Index, IndexMut, Range, RangeBounds}; use core::ptr::{self, NonNull}; use core::slice::{self, SliceIndex}; -use core::{fmt, intrinsics}; +use core::{fmt, intrinsics, ub_checks}; #[stable(feature = "extract_if", since = "1.87.0")] pub use self::extract_if::ExtractIf; @@ -1058,6 +1058,11 @@ impl<T, A: Allocator> Vec<T, A> { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { + ub_checks::assert_unsafe_precondition!( + check_library_ub, + "Vec::from_raw_parts_in requires that length <= capacity", + (length: usize = length, capacity: usize = capacity) => length <= capacity + ); unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } } @@ -1174,6 +1179,11 @@ impl<T, A: Allocator> Vec<T, A> { #[unstable(feature = "allocator_api", reason = "new API", issue = "32838")] // #[unstable(feature = "box_vec_non_null", issue = "130364")] pub unsafe fn from_parts_in(ptr: NonNull<T>, length: usize, capacity: usize, alloc: A) -> Self { + ub_checks::assert_unsafe_precondition!( + check_library_ub, + "Vec::from_parts_in requires that length <= capacity", + (length: usize = length, capacity: usize = capacity) => length <= capacity + ); unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } } @@ -1950,7 +1960,11 @@ impl<T, A: Allocator> Vec<T, A> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn set_len(&mut self, new_len: usize) { - debug_assert!(new_len <= self.capacity()); + ub_checks::assert_unsafe_precondition!( + check_library_ub, + "Vec::set_len requires that new_len <= capacity()", + (new_len: usize = new_len, capacity: usize = self.capacity()) => new_len <= capacity + ); self.len = new_len; } @@ -3695,7 +3709,7 @@ impl<T, A: Allocator> Vec<T, A> { /// This is optimal if: /// /// * The tail (elements in the vector after `range`) is empty, - /// * or `replace_with` yields fewer or equal elements than `range`’s length + /// * or `replace_with` yields fewer or equal elements than `range`'s length /// * or the lower bound of its `size_hint()` is exact. /// /// Otherwise, a temporary vector is allocated and the tail is moved twice. |
