Skip to content

Commit 1f25e65

Browse files
authored
Merge pull request #465 from Nitrokey/vecview-drop
VecView: fix memory leak of drop
2 parents c118d70 + fc133a9 commit 1f25e65

File tree

1 file changed

+54
-22
lines changed

1 file changed

+54
-22
lines changed

src/vec.rs

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,37 @@ use core::{
55
ops, ptr, slice,
66
};
77

8-
/// Workaround forbidden specialization of Drop
9-
pub trait VecDrop {
10-
// SAFETY: drop_with_len will be called to call drop in place the first `len` elements of the buffer.
11-
// Only the Owned buffer (`[MaybeUninit<T>; N]`) must drop the items
12-
// and the view (`[MaybeUninit<T>]`) drops nothing.
13-
// `drop_with_len `assumes that the buffer can contain `len` elements.
14-
unsafe fn drop_with_len(&mut self, len: usize);
8+
pub trait VecBuffer {
9+
type T;
10+
11+
fn as_vecview(vec: &VecInner<Self>) -> &VecView<Self::T>;
12+
fn as_mut_vecview(vec: &mut VecInner<Self>) -> &mut VecView<Self::T>;
1513
}
1614

17-
impl<T> VecDrop for [MaybeUninit<T>] {
18-
unsafe fn drop_with_len(&mut self, _len: usize) {
19-
// Case of a view, drop does nothing
15+
impl<T, const N: usize> VecBuffer for [MaybeUninit<T>; N] {
16+
type T = T;
17+
18+
fn as_vecview(vec: &VecInner<Self>) -> &VecView<Self::T> {
19+
vec
20+
}
21+
fn as_mut_vecview(vec: &mut VecInner<Self>) -> &mut VecView<Self::T> {
22+
vec
2023
}
2124
}
2225

23-
impl<T, const N: usize> VecDrop for [MaybeUninit<T>; N] {
24-
unsafe fn drop_with_len(&mut self, len: usize) {
25-
// NOTE(unsafe) avoid bound checks in the slicing operation
26-
// &mut buffer[..len]
27-
// SAFETY: buffer[..len] must be valid to drop given the safety requirement of the trait definition.
28-
let mut_slice = slice::from_raw_parts_mut(self.as_mut_ptr() as *mut T, len);
29-
// We drop each element used in the vector by turning into a `&mut [T]`.
30-
ptr::drop_in_place(mut_slice);
26+
impl<T> VecBuffer for [MaybeUninit<T>] {
27+
type T = T;
28+
29+
fn as_vecview(vec: &VecInner<Self>) -> &VecView<Self::T> {
30+
vec
31+
}
32+
fn as_mut_vecview(vec: &mut VecInner<Self>) -> &mut VecView<Self::T> {
33+
vec
3134
}
3235
}
3336

3437
/// <div class="warn">This is private API and should not be used</div>
35-
pub struct VecInner<B: ?Sized + VecDrop> {
38+
pub struct VecInner<B: ?Sized + VecBuffer> {
3639
len: usize,
3740
buffer: B,
3841
}
@@ -1572,10 +1575,12 @@ impl<T, const N: usize, const M: usize> From<[T; M]> for Vec<T, N> {
15721575
}
15731576
}
15741577

1575-
impl<T: ?Sized + VecDrop> Drop for VecInner<T> {
1578+
impl<T: ?Sized + VecBuffer> Drop for VecInner<T> {
15761579
fn drop(&mut self) {
1580+
let mut_slice = VecBuffer::as_mut_vecview(self).as_mut_slice();
1581+
// We drop each element used in the vector by turning into a `&mut [T]`.
15771582
// SAFETY: the buffer contains initialized data for the range 0..self.len
1578-
unsafe { self.buffer.drop_with_len(self.len) }
1583+
unsafe { ptr::drop_in_place(mut_slice) }
15791584
}
15801585
}
15811586

@@ -1953,7 +1958,7 @@ mod tests {
19531958

19541959
use static_assertions::assert_not_impl_any;
19551960

1956-
use crate::Vec;
1961+
use super::{Vec, VecView};
19571962

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

2022+
#[test]
2023+
fn drop_vecview() {
2024+
droppable!();
2025+
2026+
{
2027+
let v: Vec<Droppable, 2> = Vec::new();
2028+
let mut v: Box<VecView<Droppable>> = Box::new(v);
2029+
v.push(Droppable::new()).ok().unwrap();
2030+
v.push(Droppable::new()).ok().unwrap();
2031+
assert_eq!(Droppable::count(), 2);
2032+
v.pop().unwrap();
2033+
assert_eq!(Droppable::count(), 1);
2034+
}
2035+
2036+
assert_eq!(Droppable::count(), 0);
2037+
2038+
{
2039+
let v: Vec<Droppable, 2> = Vec::new();
2040+
let mut v: Box<VecView<Droppable>> = Box::new(v);
2041+
v.push(Droppable::new()).ok().unwrap();
2042+
v.push(Droppable::new()).ok().unwrap();
2043+
assert_eq!(Droppable::count(), 2);
2044+
}
2045+
2046+
assert_eq!(Droppable::count(), 0);
2047+
}
2048+
20172049
#[test]
20182050
fn eq() {
20192051
let mut xs: Vec<i32, 4> = Vec::new();

0 commit comments

Comments
 (0)