Fix GH-21362: ReflectionMethod::invoke/invokeArgs() rejects different Closure instances#21366
Open
iliaal wants to merge 1 commit intophp:masterfrom
Open
Fix GH-21362: ReflectionMethod::invoke/invokeArgs() rejects different Closure instances#21366iliaal wants to merge 1 commit intophp:masterfrom
iliaal wants to merge 1 commit intophp:masterfrom
Conversation
Member
|
I did not test, but based on reading the diff I think this is not quite right, yet. Instead of comparing the objects, we should compare the inner I expect this to successfully dump 0, 1, 2. All the closure instances are "of the same class". If that already works: Great, please just add that test case. |
…ent Closure instances ReflectionMethod::invokeArgs() (and invoke()) for Closure::__invoke() incorrectly accepted any Closure object, not just the one the ReflectionMethod was created from. This happened because all Closures share a single zend_ce_closure class entry, so the instanceof_function() check always passed. Fix: store the original Closure object in intern->obj during ReflectionMethod construction, then compare object identity in reflection_method_invoke() to reject different Closure instances. Closes phpGH-21362
1581e11 to
277d301
Compare
Contributor
Author
|
Good catch -- the object identity check was too strict. Updated the comparison to use Added the loop test case you suggested. All 515 reflection tests pass. P.S. Thanks for the feedback, my php internals are a bit rusty 😆 |
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 #21362
ReflectionMethod::invokeArgs()(andinvoke()) forClosure::__invoke()incorrectly accepted any Closure object, not just the one theReflectionMethodwas created from.Root cause
All Closure objects share a single
zend_ce_closureclass entry. Theinstanceof_function()check inreflection_method_invoke()compares class entries, so it always seeszend_ce_closure == zend_ce_closureand passes -- it cannot distinguish between different Closure instances.Fix
Two changes to
ext/reflection/php_reflection.c:instantiate_reflection_method(): Store the original Closure object inintern->objviaZVAL_OBJ_COPY()when reflectingClosure::__invoke(). Previously this was a no-op (/* do nothing, mptr already set */).reflection_method_invoke(): After the existinginstanceof_functioncheck passes for Closures, add an identity check (Z_OBJ_P(object) != Z_OBJ(intern->obj)) to reject different Closure instances.Test
ext/reflection/tests/gh21362.phptcovers:invokeArgs()with the correct Closure (should work)invokeArgs()with a different Closure (should throwReflectionException)invoke()with a different Closure (should throwReflectionException)