Fix panic-safety in AlignedBox::realloc (double-free on panicking element Drop) - #6
Conversation
…ment Drop) When shrinking, realloc takes the Box out of self.container and drops the tail elements. Each element's Drop is user-controlled and may panic; if it does, self.container still holds the old pointer while ownership has moved out, so AlignedBox's own Drop frees those elements a second time -- a double-free reachable from safe Rust. Drop the tail back to front under a guard that, on unwind, restores self.container/self.layout to the still-live prefix, so every element is freed exactly once. Adds a regression test.
|
Two notes:
|
|
Hi. Thanks for tracking this down and providing a fix! The first CI fail is just a missing I think there is an off-by-one error in the set value for |
Found while auditing this crate's unsafe teardown paths for panic-safety.
Summary
When shrinking, realloc takes the Box out of self.container and drops the tail
elements. If an element's Drop panics, self.container still holds the old pointer
while ownership has moved out, so AlignedBox's own Drop frees those elements a
second time, a double-free (CWE-415) reachable from safe Rust.
Fix
Drop the tail back to front under a guard. On unwind the guard restores
self.container and self.layout to the still-live prefix [0..valid], so every
element is freed exactly once. On the normal path the guard is disarmed and the
existing realloc flow continues unchanged.
Verification
Added realloc_shrink_panicking_drop_is_sound: a box of elements whose Drop panics
is shrunk, then dropped. Without the fix the second drop double-frees the tail
(glibc "double free detected", SIGABRT); with the fix it unwinds cleanly.
Existing tests pass. Confirmed on 0.3.0.