Skip to content

Commit de7bb5b

Browse files
committed
RawVecInner: add missing unsafe to unsafe fns
- RawVecInner::grow_exact causes UB if called with len and additional arguments such that len + additional is less than the current capacity. Indeed, in that case it calls Allocator::grow with a new_layout that is smaller than old_layout, which violates a safety precondition. - RawVecInner::grow_exact and RawVecInner::grow_amortized both cause UB if called with an elem_layout different from the one used to initially allocate the buffer, because in that case Allocator::grow is called with an old_layout that does not fit the allocated block, which violates a safety precondition. - Since RawVecInner::try_reserve and RawVecInner::try_reserve_exact call RawVecInner::grow_amortized and RawVecInner::grow_exact, they also cause UB if called with an elem_layout different from the one used to initially allocate the buffer. - Furthermore, these methods cause UB if called with an elem_layout where the size is not a multiple of the alignment. This is because Layout::repeat is used (in layout_array) to compute the allocation's layout when allocating, which includes padding to ensure alignment of array elements, but simple multiplication is used (in current_memory) to compute the old allocation's layout when resizing or deallocating, which would cause the layout used to resize or deallocate to not fit the allocated block, which violates a safety precondition.
1 parent 321a89b commit de7bb5b

File tree

1 file changed

+28
-15
lines changed
  • library/alloc/src/raw_vec

1 file changed

+28
-15
lines changed

library/alloc/src/raw_vec/mod.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ impl<T, A: Allocator> RawVec<T, A> {
337337
#[inline(never)]
338338
#[track_caller]
339339
pub(crate) fn grow_one(&mut self) {
340-
self.inner.grow_one(T::LAYOUT)
340+
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
341+
unsafe { self.inner.grow_one(T::LAYOUT) }
341342
}
342343

343344
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
@@ -346,7 +347,8 @@ impl<T, A: Allocator> RawVec<T, A> {
346347
len: usize,
347348
additional: usize,
348349
) -> Result<(), TryReserveError> {
349-
self.inner.try_reserve(len, additional, T::LAYOUT)
350+
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
351+
unsafe { self.inner.try_reserve(len, additional, T::LAYOUT) }
350352
}
351353

352354
/// Ensures that the buffer contains at least enough space to hold `len +
@@ -369,7 +371,8 @@ impl<T, A: Allocator> RawVec<T, A> {
369371
#[cfg(not(no_global_oom_handling))]
370372
#[track_caller]
371373
pub(crate) fn reserve_exact(&mut self, len: usize, additional: usize) {
372-
self.inner.reserve_exact(len, additional, T::LAYOUT)
374+
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
375+
unsafe { self.inner.reserve_exact(len, additional, T::LAYOUT) }
373376
}
374377

375378
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
@@ -378,7 +381,8 @@ impl<T, A: Allocator> RawVec<T, A> {
378381
len: usize,
379382
additional: usize,
380383
) -> Result<(), TryReserveError> {
381-
self.inner.try_reserve_exact(len, additional, T::LAYOUT)
384+
// SAFETY: All calls on self.inner pass T::LAYOUT as the elem_layout
385+
unsafe { self.inner.try_reserve_exact(len, additional, T::LAYOUT) }
382386
}
383387

384388
/// Shrinks the buffer down to the specified capacity. If the given amount
@@ -554,7 +558,8 @@ impl<A: Allocator> RawVecInner<A> {
554558
additional: usize,
555559
elem_layout: Layout,
556560
) {
557-
if let Err(err) = slf.grow_amortized(len, additional, elem_layout) {
561+
// SAFETY: Precondition passed to caller
562+
if let Err(err) = unsafe { slf.grow_amortized(len, additional, elem_layout) } {
558563
handle_error(err);
559564
}
560565
}
@@ -567,20 +572,24 @@ impl<A: Allocator> RawVecInner<A> {
567572
#[cfg(not(no_global_oom_handling))]
568573
#[inline]
569574
#[track_caller]
570-
fn grow_one(&mut self, elem_layout: Layout) {
571-
if let Err(err) = self.grow_amortized(self.cap.as_inner(), 1, elem_layout) {
575+
unsafe fn grow_one(&mut self, elem_layout: Layout) {
576+
// SAFETY: Precondition passed to caller
577+
if let Err(err) = unsafe { self.grow_amortized(self.cap.as_inner(), 1, elem_layout) } {
572578
handle_error(err);
573579
}
574580
}
575581

576-
fn try_reserve(
582+
unsafe fn try_reserve(
577583
&mut self,
578584
len: usize,
579585
additional: usize,
580586
elem_layout: Layout,
581587
) -> Result<(), TryReserveError> {
582588
if self.needs_to_grow(len, additional, elem_layout) {
583-
self.grow_amortized(len, additional, elem_layout)?;
589+
// SAFETY: Precondition passed to caller
590+
unsafe {
591+
self.grow_amortized(len, additional, elem_layout)?;
592+
}
584593
}
585594
unsafe {
586595
// Inform the optimizer that the reservation has succeeded or wasn't needed
@@ -591,20 +600,24 @@ impl<A: Allocator> RawVecInner<A> {
591600

592601
#[cfg(not(no_global_oom_handling))]
593602
#[track_caller]
594-
fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) {
595-
if let Err(err) = self.try_reserve_exact(len, additional, elem_layout) {
603+
unsafe fn reserve_exact(&mut self, len: usize, additional: usize, elem_layout: Layout) {
604+
// SAFETY: Precondition passed to caller
605+
if let Err(err) = unsafe { self.try_reserve_exact(len, additional, elem_layout) } {
596606
handle_error(err);
597607
}
598608
}
599609

600-
fn try_reserve_exact(
610+
unsafe fn try_reserve_exact(
601611
&mut self,
602612
len: usize,
603613
additional: usize,
604614
elem_layout: Layout,
605615
) -> Result<(), TryReserveError> {
606616
if self.needs_to_grow(len, additional, elem_layout) {
607-
self.grow_exact(len, additional, elem_layout)?;
617+
// SAFETY: Precondition passed to caller
618+
unsafe {
619+
self.grow_exact(len, additional, elem_layout)?;
620+
}
608621
}
609622
unsafe {
610623
// Inform the optimizer that the reservation has succeeded or wasn't needed
@@ -636,7 +649,7 @@ impl<A: Allocator> RawVecInner<A> {
636649
self.cap = unsafe { Cap::new_unchecked(cap) };
637650
}
638651

639-
fn grow_amortized(
652+
unsafe fn grow_amortized(
640653
&mut self,
641654
len: usize,
642655
additional: usize,
@@ -668,7 +681,7 @@ impl<A: Allocator> RawVecInner<A> {
668681
Ok(())
669682
}
670683

671-
fn grow_exact(
684+
unsafe fn grow_exact(
672685
&mut self,
673686
len: usize,
674687
additional: usize,

0 commit comments

Comments
 (0)