Fix GH-12837: Combination of phpdbg and Generator method causes memory leak#17303
Open
ndossche wants to merge 2 commits intophp:PHP-8.3from
Open
Fix GH-12837: Combination of phpdbg and Generator method causes memory leak#17303ndossche wants to merge 2 commits intophp:PHP-8.3from
ndossche wants to merge 2 commits intophp:PHP-8.3from
Conversation
…mory leak The fix for bug #72523 (d1dd474) added a check on `zend_execute_ex` to add an extra refcount to `This`. This is necessary because the VM does a re-entry here: https://github.com/php/php-src/blob/ecb90c1db7efe9d87c07e31336185fc393281035/Zend/zend_vm_def.h#L4294-L4299 and then cleans up `This` here: https://github.com/php/php-src/blob/ecb90c1db7efe9d87c07e31336185fc393281035/Zend/zend_vm_def.h#L4358-L4360 So if we don't add the refcount, we destroy `This` both in the VM and in `zend_generator_close`. The reason this causes a leak in phpdbg is because it changes the `zend_execute_ex` temporarily back to the default here for `ZEND_DO_FCALL`: https://github.com/php/php-src/blob/ecb90c1db7efe9d87c07e31336185fc393281035/sapi/phpdbg/phpdbg_prompt.c#L1820-L1827 which means that we only execute `OBJ_RELEASE` on the `This` object once in `zend_generator_close` instead of also doing it in the `ZEND_DO_FCALL` handler. To solve this, we make sure the check for the re-entrancy is consistently done by checking the `ZEND_CALL_TOP` flag instead of relying solely on `execute_ex` pointer: https://github.com/php/php-src/blob/ecb90c1db7efe9d87c07e31336185fc393281035/Zend/zend_vm_def.h#L4298
dstogov
reviewed
Jan 9, 2025
Member
dstogov
left a comment
There was a problem hiding this comment.
The problem is a bit more complex.
It seems the phpdbg "stupid hack" doesn't work.
Somehow zend_vm_call_opcode_handler() leads to execution of iterator's code with original execute_ex.
Anyway, changing zend_execute_ex at run-time is really bad idea.
This is completely incompatible with ZTS and optimizations in zend_compile.c.
I think this should be solved in phpdbg.
@bwoebi please also take a loook.
@nielsdos may be #72523 might be fixed in some better way. May be introduce some special ZEND_CALL_??? flag. Could you please think a bit more.
Anyway, this won't fix weird phpdbg behavior.
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.
The fix for bug #72523 (d1dd474) added a check on
zend_execute_exto add an extra refcount toThis. This is necessary because the VM does a re-entry here:php-src/Zend/zend_vm_def.h
Lines 4294 to 4299 in ecb90c1
and then cleans up
Thishere:php-src/Zend/zend_vm_def.h
Lines 4358 to 4360 in ecb90c1
So if we don't add the refcount, we destroy
Thisboth in the VM and inzend_generator_close.The reason this causes a leak in phpdbg is because phpdbg temporarily changes
zend_execute_exto the default here forZEND_DO_FCALL:php-src/sapi/phpdbg/phpdbg_prompt.c
Lines 1820 to 1827 in ecb90c1
OBJ_RELEASEon theThisobject once inzend_generator_closeinstead of also doing it in theZEND_DO_FCALLhandler.To solve this, we make sure the check for the re-entrancy is consistently done between
ZEND_DO_FCALLandZEND_GENERATOR_CREATEby checking theZEND_CALL_TOPflag instead of relying solely onexecute_expointer, because this flag is set whenzend_execute_exwas changed:php-src/Zend/zend_vm_def.h
Line 4298 in ecb90c1
It may over-approximate if called via
zend_call_function, as that sets theZEND_CALL_TOPflag too, but we could filter that by checking forZEND_CALL_DYNAMICtoo.Alternatively, we can fix this solely in phpdbg by also executing
GENERATOR_CREATEwith the normal execution handler, but I think the real problem is in the VM inconsistency.