Skip to content

Commit 11f950e

Browse files
committed
Don't optimize trailing args for prototype fbc
1 parent c3a3054 commit 11f950e

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

Zend/Optimizer/optimize_func_calls.c

+18-4
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,20 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o
149149
}
150150
}
151151

152+
/* arg_num is 1-based here, to match SEND encoding. */
153+
static bool has_known_send_mode(const optimizer_call_info *info, uint32_t arg_num)
154+
{
155+
if (!info->func) {
156+
return false;
157+
}
158+
159+
/* For prototype functions we should not make assumptions about arguments that are not part of
160+
* the signature: And inheriting method can add an optional by-ref argument. */
161+
return !info->is_prototype
162+
|| arg_num <= info->func->common.num_args
163+
|| (info->func->common.fn_flags & ZEND_ACC_VARIADIC);
164+
}
165+
152166
void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
153167
{
154168
zend_op *opline = op_array->opcodes;
@@ -261,7 +275,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
261275
}
262276
break;
263277
case ZEND_SEND_VAL_EX:
264-
if (call_stack[call - 1].func) {
278+
if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) {
265279
if (opline->op2_type == IS_CONST) {
266280
call_stack[call - 1].try_inline = 0;
267281
break;
@@ -276,7 +290,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
276290
}
277291
break;
278292
case ZEND_CHECK_FUNC_ARG:
279-
if (call_stack[call - 1].func) {
293+
if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) {
280294
if (opline->op2_type == IS_CONST) {
281295
call_stack[call - 1].try_inline = 0;
282296
call_stack[call - 1].func_arg_num = (uint32_t)-1;
@@ -289,7 +303,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
289303
break;
290304
case ZEND_SEND_VAR_EX:
291305
case ZEND_SEND_FUNC_ARG:
292-
if (call_stack[call - 1].func) {
306+
if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) {
293307
if (opline->op2_type == IS_CONST) {
294308
call_stack[call - 1].try_inline = 0;
295309
break;
@@ -304,7 +318,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
304318
}
305319
break;
306320
case ZEND_SEND_VAR_NO_REF_EX:
307-
if (call_stack[call - 1].func) {
321+
if (has_known_send_mode(&call_stack[call - 1], opline->op2.num)) {
308322
if (opline->op2_type == IS_CONST) {
309323
call_stack[call - 1].try_inline = 0;
310324
break;
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Adding an optional by-ref arg in a child method
3+
--FILE--
4+
<?php
5+
6+
class Test1 {
7+
public function method1() {
8+
$this->method2($x);
9+
var_dump($x);
10+
}
11+
public function method2() {}
12+
}
13+
class Test2 extends Test1 {
14+
public function method2(&$x = null) {
15+
++$x;
16+
}
17+
}
18+
(new Test2)->method1();
19+
20+
?>
21+
--EXPECT--
22+
int(1)

0 commit comments

Comments
 (0)