From 2389dbec12c2c91089f2fc9cd5ca87c5ac3f43ee Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 23 Feb 2022 14:14:46 +0100 Subject: [PATCH] Fix GH-8140: Wrong first class callable by name optimization When optimizing by name function calls, we must not replace `CALLABLE_CONVERT` opcodes, but have to keep them. --- Zend/Optimizer/optimize_func_calls.c | 8 ++++++-- ext/opcache/tests/opt/gh8140a.phpt | 16 ++++++++++++++++ ext/opcache/tests/opt/gh8140b.phpt | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 ext/opcache/tests/opt/gh8140a.phpt create mode 100644 ext/opcache/tests/opt/gh8140b.phpt diff --git a/Zend/Optimizer/optimize_func_calls.c b/Zend/Optimizer/optimize_func_calls.c index e2e16f90b8654..351010177f630 100644 --- a/Zend/Optimizer/optimize_func_calls.c +++ b/Zend/Optimizer/optimize_func_calls.c @@ -200,14 +200,18 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); literal_dtor(&ZEND_OP2_LITERAL(fcall)); fcall->op2.constant = fcall->op2.constant + 1; - opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + if (opline->opcode != ZEND_CALLABLE_CONVERT) { + opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + } } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); literal_dtor(&op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant + 2]); fcall->op2.constant = fcall->op2.constant + 1; - opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + if (opline->opcode != ZEND_CALLABLE_CONVERT) { + opline->opcode = zend_get_call_op(fcall, call_stack[call].func); + } } else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL || fcall->opcode == ZEND_INIT_METHOD_CALL || fcall->opcode == ZEND_NEW) { diff --git a/ext/opcache/tests/opt/gh8140a.phpt b/ext/opcache/tests/opt/gh8140a.phpt new file mode 100644 index 0000000000000..03f097c77c5ce --- /dev/null +++ b/ext/opcache/tests/opt/gh8140a.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-8140 (Wrong first class callable by name optimization) +--FILE-- + +--EXPECT-- +Hello, world! diff --git a/ext/opcache/tests/opt/gh8140b.phpt b/ext/opcache/tests/opt/gh8140b.phpt new file mode 100644 index 0000000000000..60da3a79e1408 --- /dev/null +++ b/ext/opcache/tests/opt/gh8140b.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-8140 (Wrong first class callable by name optimization) +--FILE-- + +--EXPECT-- +Hello, world!