Repository navigation
Fix unsafe reclamation when dropping maps with a shared collector - #103
Open
jimezesinachi wants to merge 1 commit into
Open
jimezesinachi wants to merge 1 commit into
jimezesinachi wants to merge 1 commit into
Conversation
Signed-off-by: Jim Ezesinachi <ezesinachijim@gmail.com>
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
Fixes a use-after-free that can occur when multiple Papaya maps share the same Seize collector.
When a
HashMapis dropped, Papaya currently callsCollector::reclaim_all()before destroying the map's table chain. This is safe when the map exclusively owns its collector, but not when the collector was supplied throughHashMap::builder().shared_collector(...).With a shared collector, another map may still have an active guard protecting retired objects. Calling
reclaim_all()ignores that protection and immediately reclaims every pending object associated with the collector. References protected by those active guards can then point to freed memory.The issue and standalone reproducer are documented in:
#102
Changes
The map drop path now distinguishes between exclusive and shared collector ownership.
Exclusively owned collector
When
Arc::get_mut(&mut self.collector)succeeds, no other strong or weak references to the collector exist. The map can therefore preserve the existing behavior:This retains eager reclamation for ordinary maps that own their collector.
Shared collector
When the collector has other owners, the map no longer calls
reclaim_all().Instead, it:
Only the table chain owned by the map being dropped is retired. Pending objects belonging to other maps using the same collector are left under the collector's normal reclamation rules.
The existing table-chain destruction logic has been extracted into
drop_tables()so both ownership paths use the same cleanup implementation.Regression Test
The new test recreates the failure using three maps backed by one shared collector:
The test verifies that dropping the third map does not reclaim the protected value. After the guard and remaining owners are dropped, it verifies that the value is reclaimed exactly once.
Validation
cargo check --all-targetspasses.Fixes #102