Fix crash when a partial skips a param with a constant default#22804
Open
iliaal wants to merge 1 commit into
Open
Fix crash when a partial skips a param with a constant default#22804iliaal wants to merge 1 commit into
iliaal wants to merge 1 commit into
Conversation
When a partial leaves an optional parameter unbound (a positional gap from named arguments) and its default is a constant expression, the default AST was compiled into the forwarding call as an uncompilable ZEND_AST_CONSTANT node: an assertion in debug builds, undefined behavior otherwise. For a user function, skip the parameter and pass the following arguments by name so the target applies its own default at call time; this materializes no value and handles every default kind, including enum cases that cannot be a literal. Internal functions still pass an explicit default and error if it is not introspectable.
Member
|
Interesting one. It looks like an edge case with Unfortunately, passing by name doesn't work in all cases (or requires more work), for example: Will generate: which is invalid due to the use of unpacking after a named param. We would need to unpack at compile time, but we may run into other issues. Possible alternative ways to fix this:
I have a preference for the first one. wdyt? |
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.
A partial that leaves an optional parameter unbound via a named-argument gap, where that parameter's default is a constant expression, crashes the compiler.
f(a: 10, c: ?)forfunction f($a, $b = SOME_CONST, $c = 0)compiled the callee default into the generated forwarding call as aZEND_AST_CONSTANTnode, whichzend_compile_expr_innerhas no case for:ZEND_ASSERT(0)in debug,__builtin_unreachableUB in release. A plain literal default ($b = 5) is unaffected.For a user function, this skips the unbound parameter in the forwarding call and passes the following arguments by name, so the target applies its own default at call time. That matches a normal call exactly (verified for global constants,
self::class constants, and enum cases) and materializes no value, so it is safe under opcache for defaults that cannot be stored as a literal, such as enum cases. Internal functions are unchanged: they still pass an explicit default and error when it is not introspectable.