Skip to content

Commit 8bdf0f3

Browse files
committed
fix FillError::fill double free
1 parent fe8d917 commit 8bdf0f3

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

library/core/src/array/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::convert::{Infallible, TryFrom};
1212
use crate::fmt;
1313
use crate::hash::{self, Hash};
1414
use crate::marker::Unsize;
15-
use crate::mem::MaybeUninit;
15+
use crate::mem::{self, MaybeUninit};
1616
use crate::slice::{Iter, IterMut};
1717

1818
mod iter;
@@ -259,10 +259,14 @@ impl<T, const N: usize> FillError<T, N> {
259259
// an array of `T`.
260260
//
261261
// With that, this initialization satisfies the invariants.
262+
//
262263
// FIXME: actually use `mem::transmute` here, once it
263264
// works with const generics:
264265
// `mem::transmute::<[MaybeUninit<T>; N], [T; N]>(array)`
265-
Ok(unsafe { crate::ptr::read(&self.array as *const [MaybeUninit<T>; N] as *const [T; N]) })
266+
let arr = unsafe { crate::mem::transmute_copy::<_, [T; N]>(&self.array) };
267+
// We forget `self` to not drop anything here.
268+
mem::forget(self);
269+
Ok(arr)
266270
}
267271
}
268272

library/core/tests/array.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ fn array_collects() {
341341

342342
#[test]
343343
#[should_panic(expected = "test succeeded")]
344-
fn array_collect_drop_safety() {
344+
fn array_collect_panic_safety() {
345345
use core::sync::atomic::AtomicUsize;
346346
use core::sync::atomic::Ordering;
347347
static DROPPED: AtomicUsize = AtomicUsize::new(0);
@@ -368,3 +368,22 @@ fn array_collect_drop_safety() {
368368
assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
369369
panic!("test succeeded")
370370
}
371+
372+
#[test]
373+
fn array_collect_no_double_drop() {
374+
use core::sync::atomic::AtomicUsize;
375+
use core::sync::atomic::Ordering;
376+
static DROPPED: AtomicUsize = AtomicUsize::new(0);
377+
struct DropCounter;
378+
impl Drop for DropCounter {
379+
fn drop(&mut self) {
380+
DROPPED.fetch_add(1, Ordering::SeqCst);
381+
}
382+
}
383+
384+
const LEN: usize = 10;
385+
let items = [0; LEN];
386+
let _ = FillError::<DropCounter, 10>::new().fill(items.iter().map(|_| DropCounter)).unwrap();
387+
388+
assert_eq!(DROPPED.load(Ordering::SeqCst), LEN);
389+
}

0 commit comments

Comments
 (0)