Skip to content

Commit

Permalink
Fix memory leak on VecView drop
Browse files Browse the repository at this point in the history
Drop must also be implemented on `VecView` for the cases wher the `VecView` is owned
even if it is `!Sized`.

This can happen when it is boxed.
  • Loading branch information
sosthene-nitrokey committed May 23, 2024
1 parent 804fa58 commit ec6700a
Showing 1 changed file with 34 additions and 7 deletions.
41 changes: 34 additions & 7 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ pub trait VecDrop {
}

impl<T> VecDrop for [MaybeUninit<T>] {
unsafe fn drop_with_len(&mut self, _len: usize) {
// Case of a view, drop does nothing
}
}

impl<T, const N: usize> VecDrop for [MaybeUninit<T>; N] {
unsafe fn drop_with_len(&mut self, len: usize) {
// NOTE(unsafe) avoid bound checks in the slicing operation
// &mut buffer[..len]
Expand All @@ -31,6 +25,12 @@ impl<T, const N: usize> VecDrop for [MaybeUninit<T>; N] {
}
}

impl<T, const N: usize> VecDrop for [MaybeUninit<T>; N] {
unsafe fn drop_with_len(&mut self, len: usize) {
VecDrop::drop_with_len(self.as_mut_slice(), len)
}
}

/// <div class="warn">This is private API and should not be used</div>
pub struct VecInner<B: ?Sized + VecDrop> {
len: usize,
Expand Down Expand Up @@ -1953,7 +1953,7 @@ mod tests {

use static_assertions::assert_not_impl_any;

use crate::Vec;
use super::{Vec, VecView};

// Ensure a `Vec` containing `!Send` values stays `!Send` itself.
assert_not_impl_any!(Vec<*const (), 4>: Send);
Expand Down Expand Up @@ -2014,6 +2014,33 @@ mod tests {
assert_eq!(Droppable::count(), 0);
}

#[test]
fn drop_vecview() {
droppable!();

{
let v: Vec<Droppable, 2> = Vec::new();
let mut v: Box<VecView<Droppable>> = Box::new(v);
v.push(Droppable::new()).ok().unwrap();
v.push(Droppable::new()).ok().unwrap();
assert_eq!(Droppable::count(), 2);
v.pop().unwrap();
assert_eq!(Droppable::count(), 1);
}

assert_eq!(Droppable::count(), 0);

{
let v: Vec<Droppable, 2> = Vec::new();
let mut v: Box<VecView<Droppable>> = Box::new(v);
v.push(Droppable::new()).ok().unwrap();
v.push(Droppable::new()).ok().unwrap();
assert_eq!(Droppable::count(), 2);
}

assert_eq!(Droppable::count(), 0);
}

#[test]
fn eq() {
let mut xs: Vec<i32, 4> = Vec::new();
Expand Down

0 comments on commit ec6700a

Please sign in to comment.