Skip to content

Commit 4298b9d

Browse files
authored
Merge pull request #10 from JOE1994/panic_safety_fix
panic safety fix: guard against double drop
2 parents 119f5ec + 76bc9b5 commit 4298b9d

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

src/array.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -174,26 +174,24 @@ macro_rules! impl_array {
174174
where
175175
F: FnMut(T) -> U,
176176
{
177-
fn map_array(mut values: [T; $size], mut f: F) -> Self {
177+
fn map_array(values: [T; $size], mut f: F) -> Self {
178178
use std::{
179-
mem::forget,
179+
mem::{ManuallyDrop, MaybeUninit},
180180
ptr::{read, write},
181181
};
182182

183+
// Use `ManuallyDrop<_>` to guard against panic safety issue.
184+
// Upon panic in `f`, `values` isn't dropped
185+
// and thus item copied by `read()` is dropped only once.
186+
let mut values = ManuallyDrop::new(values);
183187
unsafe {
184-
// All elements of `result` is written.
185-
// Each element of `values` read once and then forgotten.
186-
// Hence safe in case `f` never panics.
187-
// TODO: Make it panic-safe.
188-
let mut result: ::std::mem::MaybeUninit<[U; $size]> =
189-
::std::mem::MaybeUninit::zeroed();
188+
let mut result: MaybeUninit<[U; $size]> = MaybeUninit::zeroed();
190189
for i in 0..$size {
191190
write(
192191
result.as_mut_ptr().cast::<U>().add(i),
193192
f(read(&mut values[i])),
194193
);
195194
}
196-
forget(values);
197195
result.assume_init()
198196
}
199197
}

0 commit comments

Comments
 (0)