Skip to content

Fix panic-safety in LinkedHashMap::clear (double-free on panicking value Drop) - #9

Open
tooson9010-spec wants to merge 1 commit into
PsiACE:mainfrom
tooson9010-spec:fix/clear-panic-safety
Open

tooson9010-spec wants to merge 1 commit into
PsiACE:mainfrom
tooson9010-spec:fix/clear-panic-safety

Conversation

@tooson9010-spec

Copy link
Copy Markdown

Found while auditing this crate's unsafe teardown paths for panic-safety.

Summary

clear frees the value nodes, running each value's Drop, then resets the guard
links. If a value's Drop panics after some nodes are freed, the reset is skipped
and the sentinel still points at freed memory. The map's destructor later walks
that chain and frees it again, a double-free (CWE-415) reachable from safe Rust.

Fix

Reset the guard links before freeing instead of after. The sentinel then points
at an empty list, so a panic during freeing can't reach the second traversal. On
panic the unreached nodes leak, which is safe. LinkedHashSet::clear delegates to
LinkedHashMap::clear and is fixed by the same change.

Verification

Added clear_panicking_value_drop_is_sound: values that panic on Drop are cleared
under catch_unwind, then the map is dropped. Without the fix the second traversal
double-frees the chain (glibc "double free detected", SIGABRT); with the fix it
unwinds cleanly. Existing tests pass. Confirmed on 0.3.2.

…lue Drop)

clear frees the value nodes (running each value's user-controlled Drop) and
resets the sentinel's guard links afterwards. A value Drop that panics partway
leaves the reset unrun, so the guard still points into freed memory; the map's
own destructor then walks that chain again and frees it a second time -- a
double-free reachable from safe Rust. Reset the guard links before freeing so
unwinding leaves an empty, self-consistent list. LinkedHashSet::clear delegates
to LinkedHashMap::clear and is fixed by the same change. Adds a regression test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant