Fix panic-safety unsoundness in SmallMap::retain (use-after-free when an element's Drop panics) - #10
Merged
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
Author
|
@ihciah Thanks for merging! Once this is released, I'd like to file a RustSec advisory so users still on 0.1.5 are notified. Would that be alright with you? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RawInline::retain(reached viaSmallMap::retainon an inline map) is notpanic-safe. It
drop_in_places a rejected entry and only then callseraseto dothe swap-delete and decrement
len:If the entry's
Droppanics,erasenever runs, solenstill counts thealready-dropped slot. When the map is later dropped,
drop_elementswalks0..lenand drops that slot again — a double-free (CWE-415) / use-after-free (CWE-416)
reachable from safe Rust. This is a soundness issue.
Fix
Read the rejected entry out of the slot with
ptr::read, runerase(swap-delete +lendecrement), and only then drop it. Once the entry has been moved out and thestructure is consistent, a panicking
Dropcan no longer leave a slot thatdrop_elementswould revisit.Testing
Added
retain_panicking_drop_keeps_map_consistent: an element whoseDroppanics isremoved under
catch_unwind, then the map is dropped. Under AddressSanitizer(
-Zsanitizer=address), the original code reports a heap-use-after-free on thistest; with the fix the test passes. The full existing test suite also still passes.
Disclosure
Found while researching panic-safety in Rust crates. Confirmed on 0.1.5.