|
4 | 4 |
|
5 | 5 | use super::{AllocError, Flags};
|
6 | 6 | use alloc::vec::Vec;
|
| 7 | +use core::ptr; |
7 | 8 |
|
8 | 9 | /// Extensions to [`Vec`].
|
9 | 10 | pub trait VecExt<T>: Sized {
|
@@ -134,14 +135,20 @@ impl<T> VecExt<T> for Vec<T> {
|
134 | 135 | let new_cap = core::cmp::max(cap * 2, len.checked_add(additional).ok_or(AllocError)?);
|
135 | 136 | let layout = core::alloc::Layout::array::<T>(new_cap).map_err(|_| AllocError)?;
|
136 | 137 |
|
137 |
| - let (ptr, len, cap) = destructure(self); |
| 138 | + let (old_ptr, len, cap) = destructure(self); |
| 139 | + |
| 140 | + // We need to make sure that `ptr` is either NULL or comes from a previous call to |
| 141 | + // `krealloc_aligned`. A `Vec<T>`'s `ptr` value is not guaranteed to be NULL and might be |
| 142 | + // dangling after being created with `Vec::new`. Instead, we can rely on `Vec<T>`'s capacity |
| 143 | + // to be zero if no memory has been allocated yet. |
| 144 | + let ptr = if cap == 0 { ptr::null_mut() } else { old_ptr }; |
138 | 145 |
|
139 | 146 | // SAFETY: `ptr` is valid because it's either NULL or comes from a previous call to
|
140 | 147 | // `krealloc_aligned`. We also verified that the type is not a ZST.
|
141 | 148 | let new_ptr = unsafe { super::allocator::krealloc_aligned(ptr.cast(), layout, flags) };
|
142 | 149 | if new_ptr.is_null() {
|
143 | 150 | // SAFETY: We are just rebuilding the existing `Vec` with no changes.
|
144 |
| - unsafe { rebuild(self, ptr, len, cap) }; |
| 151 | + unsafe { rebuild(self, old_ptr, len, cap) }; |
145 | 152 | Err(AllocError)
|
146 | 153 | } else {
|
147 | 154 | // SAFETY: `ptr` has been reallocated with the layout for `new_cap` elements. New cap
|
|
0 commit comments