Fix use-after-free when a destructor bails out during zend_hash_clean()#22710
Open
iliaal wants to merge 1 commit into
Open
Fix use-after-free when a destructor bails out during zend_hash_clean()#22710iliaal wants to merge 1 commit into
iliaal wants to merge 1 commit into
Conversation
zend_hash_clean() runs the element destructors and resets the table only after the loop, so a zend_bailout (memory_limit, timeout, E_USER_ERROR) from a destructor mid-walk abandons the walk with already-destroyed slots still present in the still-reachable table, and the later teardown destroys them a second time. Move each element to a local and set the slot to IS_UNDEF before running its destructor, so a bailed-out clean leaves consumed slots that the teardown skips. The buffer and packed/map shape are kept, so callers that clean during iteration are unaffected.
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.
zend_hash_clean() runs each element's destructor and resets the table only after the loop, so a zend_bailout from a destructor (memory_limit, timeout, E_USER_ERROR) leaves already-destroyed slots in a still-reachable table and shutdown teardown frees them a second time. session_unset() on a $_SESSION whose value has a bailing destructor reproduces it. The fix moves each element into a local and clears its slot to IS_UNDEF before running the destructor, so a bailed-out clean leaves consumed slots that teardown skips; the buffer and packed/map shape are preserved, so cleaning during iteration is unaffected.