Skip to content

Commit

Permalink
Use ManuallyDrop<T> instead of mem::forget in scopeguard
Browse files Browse the repository at this point in the history
With field retagging in SB, this causes UB because the read out value
is invalidated by the move into `mem::forget`. Using `ManuallyDrop<T>`
avoids the problem.
  • Loading branch information
Nilstrieb committed Sep 6, 2022
1 parent 22c7dbc commit f4c9597
Showing 1 changed file with 6 additions and 8 deletions.
14 changes: 6 additions & 8 deletions src/scopeguard.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Extracted from the scopeguard crate
use core::{
mem,
mem::ManuallyDrop,
ops::{Deref, DerefMut},
ptr,
};
Expand Down Expand Up @@ -28,15 +28,13 @@ where
#[inline]
pub fn into_inner(guard: Self) -> T {
// Cannot move out of Drop-implementing types, so
// ptr::read the value and forget the guard.
// ptr::read the value out of a ManuallyDrop<Self>
// Don't use mem::forget as that might invalidate value
let guard = ManuallyDrop::new(guard);
unsafe {
let value = ptr::read(&guard.value);
// read the closure so that it is dropped, and assign it to a local
// variable to ensure that it is only dropped after the guard has
// been forgotten. (In case the Drop impl of the closure, or that
// of any consumed captured variable, panics).
let _dropfn = ptr::read(&guard.dropfn);
mem::forget(guard);
// read the closure so that it is dropped
let _ = ptr::read(&guard.dropfn);
value
}
}
Expand Down

0 comments on commit f4c9597

Please sign in to comment.