[php-src] PHP-8.6: Merge branch 'PHP-8.5' into PHP-8.6
| From: | ndossche | Date: | Thu, 22 Oct 2026 08:48:02 +0000 |
| Subject: | [php-src] PHP-8.6: Merge branch 'PHP-8.5' into PHP-8.6 | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-142553@lists.php.net to get a copy of this message | ||
Author: ndossche (ndossche)
Date: 2026-10-22T10:47:45+02:00
Commit: https://github.com/php/php-src/commit/8f38f7ad741360b908c065da9e1724c8bd99f03a
Raw diff: https://github.com/php/php-src/commit/8f38f7ad741360b908c065da9e1724c8bd99f03a.diff
Merge branch 'PHP-8.5' into PHP-8.6
* PHP-8.5:
JIT: Fix function JIT level 1 crash on FETCH_OBJ_FUNC_ARG of a hooked property
Changed paths:
A ext/opcache/tests/jit/gh24398.phpt
A ext/opcache/tests/jit/gh24398_002.phpt
M NEWS
M ext/opcache/jit/zend_jit.c
M ext/opcache/jit/zend_jit_ir.c
M ext/opcache/jit/zend_jit_trace.c
Diff:
diff --git a/NEWS b/NEWS
index 295d724a257d..9a3a044a015f 100644
--- a/NEWS
+++ b/NEWS
@@ -75,6 +75,8 @@ PHP NEWS
reference check). (ndossche)
. Fixed bug GH-24437 (JIT: Fix OP_DATA read from an unwritten slot in
zend_jit_assign_dim_op()). (waroad)
+ . Fixed bug GH-24398 (JIT: minimal JIT segfault when a hooked property is
+ passed to a run-time-resolved function). (waroad)
- PDO:
. Fixed invalid ATTR_ORACLE_NULLS values being accepted and truncated.
diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c
index 7b73bbd88e25..c293e440bb8e 100644
--- a/ext/opcache/jit/zend_jit.c
+++ b/ext/opcache/jit/zend_jit.c
@@ -2888,6 +2888,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const
zend_op
call_level--;
}
break;
+ /* FETCH_OBJ_FUNC_ARG may dispatch into the FETCH_OBJ_R handler (if sent by value). */
+ case ZEND_FETCH_OBJ_FUNC_ARG:
case ZEND_FETCH_OBJ_R:
if (!zend_jit_handler(&ctx, opline,
zend_may_throw(opline, ssa_op, op_array, ssa))) {
diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c
index 0e7549a85630..bde6f8558031 100644
--- a/ext/opcache/jit/zend_jit_ir.c
+++ b/ext/opcache/jit/zend_jit_ir.c
@@ -17238,7 +17238,8 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array
*op_arr
opline->opcode == ZEND_GENERATOR_CREATE ||
opline->opcode == ZEND_INCLUDE_OR_EVAL ||
/* May enter a simple get hook. */
- opline->opcode == ZEND_FETCH_OBJ_R) {
+ opline->opcode == ZEND_FETCH_OBJ_R ||
+ opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
jit_STORE_IP(jit, ir_AND_A(ref, ir_CONST_ADDR(~ZEND_VM_ENTER_BIT)));
} else {
@@ -17266,7 +17267,8 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array
*op_arr
opline->opcode == ZEND_GENERATOR_CREATE ||
opline->opcode == ZEND_INCLUDE_OR_EVAL ||
/* May enter a simple get hook. */
- opline->opcode == ZEND_FETCH_OBJ_R) {
+ opline->opcode == ZEND_FETCH_OBJ_R ||
+ opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG) {
ir_ref addr = jit_EG(current_execute_data);
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index 721f87a03f50..906a877a4097 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -348,6 +348,8 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
// TODO: recompilation may change target ???
return 0;
#endif
+ /* FETCH_OBJ_FUNC_ARG may dispatch into the FETCH_OBJ_R handler (if sent by value). */
+ case ZEND_FETCH_OBJ_FUNC_ARG:
case ZEND_FETCH_OBJ_R:
if (opline->op2_type == IS_CONST) {
const zend_class_entry *ce = opline->op1_type == IS_UNUSED ? op_array->scope : NULL;
diff --git a/ext/opcache/tests/jit/gh24398.phpt b/ext/opcache/tests/jit/gh24398.phpt
new file mode 100644
index 000000000000..948ac8f1b261
--- /dev/null
+++ b/ext/opcache/tests/jit/gh24398.phpt
@@ -0,0 +1,36 @@
+--TEST--
+GH-24398: Function JIT level 1 crash on FETCH_OBJ_FUNC_ARG of a hooked property
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.jit_buffer_size=64M
+opcache.jit=1201
+--EXTENSIONS--
+opcache
+--FILE--
+<?php
+
+class C {
+ public $prop {
+ get => 5;
+ }
+}
+
+if (true) {
+ function g($x) {
+ return $x;
+ }
+}
+
+function f($o) {
+ return g($o->prop);
+}
+
+$c = new C();
+var_dump(f($c));
+var_dump(f($c));
+
+?>
+--EXPECT--
+int(5)
+int(5)
diff --git a/ext/opcache/tests/jit/gh24398_002.phpt b/ext/opcache/tests/jit/gh24398_002.phpt
new file mode 100644
index 000000000000..b8b0c0481c77
--- /dev/null
+++ b/ext/opcache/tests/jit/gh24398_002.phpt
@@ -0,0 +1,44 @@
+--TEST--
+GH-24398 (tracing): FETCH_OBJ_FUNC_ARG of a hooked property with unknown send mode
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.jit_buffer_size=64M
+opcache.jit=tracing
+opcache.jit_hot_loop=1
+--EXTENSIONS--
+opcache
+--FILE--
+<?php
+
+class A {
+ public $prop = 5;
+}
+
+class B {
+ public $prop {
+ get => 5;
+ }
+}
+
+if (true) {
+ function g($x) {
+ return $x;
+ }
+}
+
+function f($o) {
+ // The named argument leaves the send mode unknown to the tracing JIT,
+ // so FETCH_OBJ_FUNC_ARG is executed by the VM handler.
+ return g(x: $o->prop);
+}
+
+$sum = 0;
+foreach ([new A, new A, new A, new B, new B, new B] as $o) {
+ $sum += f($o);
+}
+var_dump($sum);
+
+?>
+--EXPECT--
+int(30)