Skip to content

Commit

Permalink
Merge pull request #10 from JOE1994/panic_safety_fix
Browse files Browse the repository at this point in the history
panic safety fix: guard against double drop
  • Loading branch information
zakarumych authored Jan 11, 2021
2 parents 119f5ec + 76bc9b5 commit 4298b9d
Showing 1 changed file with 7 additions and 9 deletions.
16 changes: 7 additions & 9 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,26 +174,24 @@ macro_rules! impl_array {
where
F: FnMut(T) -> U,
{
fn map_array(mut values: [T; $size], mut f: F) -> Self {
fn map_array(values: [T; $size], mut f: F) -> Self {
use std::{
mem::forget,
mem::{ManuallyDrop, MaybeUninit},
ptr::{read, write},
};

// Use `ManuallyDrop<_>` to guard against panic safety issue.
// Upon panic in `f`, `values` isn't dropped
// and thus item copied by `read()` is dropped only once.
let mut values = ManuallyDrop::new(values);
unsafe {
// All elements of `result` is written.
// Each element of `values` read once and then forgotten.
// Hence safe in case `f` never panics.
// TODO: Make it panic-safe.
let mut result: ::std::mem::MaybeUninit<[U; $size]> =
::std::mem::MaybeUninit::zeroed();
let mut result: MaybeUninit<[U; $size]> = MaybeUninit::zeroed();
for i in 0..$size {
write(
result.as_mut_ptr().cast::<U>().add(i),
f(read(&mut values[i])),
);
}
forget(values);
result.assume_init()
}
}
Expand Down

0 comments on commit 4298b9d

Please # to comment.