Fix crash when a partial skips a param with a constant default#22804
Conversation
|
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? |
c2117da to
b3c097d
Compare
Const exprs represent a constant fetch that could not be evaluated at compile time as ZEND_AST_CONSTANT, which zend_compile_expr_inner() had no case for, so compiling such a default into a partial's forwarding call hit ZEND_ASSERT(0). Compile it to ZEND_FETCH_CONSTANT using the name already resolved by zend_compile_const_expr_const(). zp_compile_forwarding_call() also dropped the reference it took on a constant-expression default value. Closes phpGH-22804
|
Went with the first one. zend_compile_expr_inner() now compiles Also released the reference |
Const exprs represent a constant fetch that could not be evaluated at compile time as ZEND_AST_CONSTANT, which zend_compile_expr_inner() had no case for, so compiling such a default into a partial's forwarding call hit ZEND_ASSERT(0). Compile it to ZEND_FETCH_CONSTANT using the name already resolved by zend_compile_const_expr_const(). zp_compile_forwarding_call() also dropped the reference it took on a constant-expression default value. Closes phpGH-22804
b3c097d to
6de6c31
Compare
A partial that leaves an optional parameter unbound through a named-argument gap crashes the compiler when that parameter's default is a constant expression:
f(a: 10, c: ?)againstfunction f($a, $b = SOME_CONST, $c = 0). Const exprs represent a constant fetch as ZEND_AST_CONSTANT when it could not be evaluated at compile time, and zend_compile_expr_inner() has no case for that kind, so compiling the callee default into the generated forwarding call hits ZEND_ASSERT(0) in debug and __builtin_unreachable in release. A literal default is a ZEND_AST_ZVAL and is unaffected.zend_compile_expr_inner() now compiles ZEND_AST_CONSTANT to ZEND_FETCH_CONSTANT, reusing the name zend_compile_const_expr_const() already resolved along with its unqualified-in-namespace flag. The constant is looked up when the partial is invoked, as in a direct call, and its value is never folded into the forwarding op_array's literals.
zp_compile_forwarding_call() also dropped the reference it takes on a constant-expression default value, which leaks on master for class-constant and enum-case defaults.