Repository navigation
Create named closures like Closure::fromCallable() - #60
Merged
Merged
Conversation
nicolas-grekas
force-pushed
the
fuzz-named-closures
branch
2 times, most recently
from
September 29, 2026 21:03
4209a8c to
b07c146
Compare
deepclone_from_array() gave the closure over a method the scope of the class it looked the method up on: for an inherited method, the private properties of the parent class weren't reachable anymore. The closure now gets the scope of the class that declares the method, and is called on the class of its object, or on the named class, like with Closure::fromCallable(). For static methods, deepclone_to_array() exports that called class instead of the declaring one, which static:: resolves to. Named closures over a non-static method without an object, or over a method of a class that their object or class doesn't extend, are rejected instead of being created, and a top-level one whose function doesn't exist throws instead of returning null. The ones over a method that __call() or __callStatic() handles are created with Closure::fromCallable(), instead of returning null too. On PHP 8.4+, the shape of the named closures that lazy objects hold is checked right away, like const-expr closures are against the allowed classes, instead of when these objects are first used.
nicolas-grekas
force-pushed
the
fuzz-named-closures
branch
from
September 29, 2026 22:07
b07c146 to
cc5a725
Compare
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.
Also found by the differential fuzzing of the polyfill against the extension.
deepclone_from_array()gave the closure over a method the scope of the class it looked the method up on. For an inherited method, the private properties of the parent class weren't reachable anymore:The closure now gets the scope of the class that declares the method, and is called on the class of its object or on the named class, like with
Closure::fromCallable(). For static methods,deepclone_to_array()exports that called class instead of the declaring one, as the polyfill does, so thatstatic::resolves the same.Named closures over a non-static method without an object, or over a method of a class that their object or class doesn't extend, are now rejected, a top-level one whose function doesn't exist throws instead of returning
null, the ones over a method that__call()or__callStatic()handles are created withClosure::fromCallable(), and on PHP 8.4+ the shape of the ones lazy objects hold is checked right away, as the README says for malformed payloads.