Skip to content

Commit 33cd61c

Browse files
committed
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. Closes GH-8144.
1 parent 5d907df commit 33cd61c

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ PHP NEWS
99
variables. (ilutov)
1010
. Fixed bug GH-7958 (Nested CallbackFilterIterator is leaking memory). (cmb)
1111
. Fixed bug GH-8074 (Wrong type inference of range() result). (cmb)
12+
. Fixed bug GH-8140 (Wrong first class callable by name optimization). (cmb)
1213

1314
- GD:
1415
. Fixed libpng warning when loading interlaced images. (Brett)

Zend/Optimizer/optimize_func_calls.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,18 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
200200
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
201201
literal_dtor(&ZEND_OP2_LITERAL(fcall));
202202
fcall->op2.constant = fcall->op2.constant + 1;
203-
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
203+
if (opline->opcode != ZEND_CALLABLE_CONVERT) {
204+
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
205+
}
204206
} else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
205207
fcall->opcode = ZEND_INIT_FCALL;
206208
fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func);
207209
literal_dtor(&op_array->literals[fcall->op2.constant]);
208210
literal_dtor(&op_array->literals[fcall->op2.constant + 2]);
209211
fcall->op2.constant = fcall->op2.constant + 1;
210-
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
212+
if (opline->opcode != ZEND_CALLABLE_CONVERT) {
213+
opline->opcode = zend_get_call_op(fcall, call_stack[call].func);
214+
}
211215
} else if (fcall->opcode == ZEND_INIT_STATIC_METHOD_CALL
212216
|| fcall->opcode == ZEND_INIT_METHOD_CALL
213217
|| fcall->opcode == ZEND_NEW) {

ext/opcache/tests/opt/gh8140a.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-8140 (Wrong first class callable by name optimization)
3+
--FILE--
4+
<?php
5+
namespace Test;
6+
7+
function greeter(string $name) {
8+
echo "Hello, ${name}!";
9+
}
10+
11+
$mycallable = greeter(...);
12+
13+
$mycallable("world");
14+
?>
15+
--EXPECT--
16+
Hello, world!

ext/opcache/tests/opt/gh8140b.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
GH-8140 (Wrong first class callable by name optimization)
3+
--FILE--
4+
<?php
5+
$mycallable = greeter(...);
6+
7+
function greeter(string $name) {
8+
echo "Hello, ${name}!";
9+
}
10+
11+
$mycallable("world");
12+
?>
13+
--EXPECT--
14+
Hello, world!

0 commit comments

Comments
 (0)