1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Backport fix GH-17307

This is a backport of GH-17319 to fix GH-17307 on lower branches.

Closes GH-17424.
This commit is contained in:
Niels Dossche
2025-01-09 20:14:13 +01:00
parent a2a7287b87
commit e8fce295bc
4 changed files with 45 additions and 16 deletions

3
NEWS
View File

@@ -25,6 +25,9 @@ PHP NEWS
- Intl:
. Fixed bug GH-11874 (intl causing segfault in docker images). (nielsdos)
- Opcache:
. Fixed bug GH-17307 (Internal closure causes JIT failure). (nielsdos)
- PHPDBG:
. Fix crashes in function registration + test. (nielsdos, Girgias)

View File

@@ -8471,6 +8471,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
{
uint32_t used_stack;
bool stack_check = 1;
const size_t func_type_offset = is_closure ? offsetof(zend_closure, func.type) : offsetof(zend_function, type);
// REG0 -> zend_function
// FCARG1 -> used_stack
@@ -8484,15 +8485,11 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value + ZEND_OBSERVER_ENABLED) * sizeof(zval);
| // if (EXPECTED(ZEND_USER_CODE(func->type))) {
if (!is_closure) {
| LOAD_32BIT_VAL FCARG1w, used_stack
| // Check whether REG0 is an internal function.
| ldrb TMP1w, [REG0, #offsetof(zend_function, type)]
| TST_32_WITH_CONST TMP1w, 1, TMP2w
| bne >1
} else {
| LOAD_32BIT_VAL FCARG1w, used_stack
}
| LOAD_32BIT_VAL FCARG1w, used_stack
| // Check whether REG0 is an internal function.
| ldrb TMP1w, [REG0, #func_type_offset]
| TST_32_WITH_CONST TMP1w, 1, TMP2w
| bne >1
| // used_stack += (func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args)) * sizeof(zval);
| LOAD_32BIT_VAL REG2w, opline->extended_value
if (!is_closure) {

View File

@@ -9072,6 +9072,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
{
uint32_t used_stack;
bool stack_check = 1;
const size_t func_type_offset = is_closure ? offsetof(zend_closure, func.type) : offsetof(zend_function, type);
if (func) {
used_stack = zend_vm_calc_used_stack(opline->extended_value, func);
@@ -9082,13 +9083,9 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value + ZEND_OBSERVER_ENABLED) * sizeof(zval);
| // if (EXPECTED(ZEND_USER_CODE(func->type))) {
if (!is_closure) {
| test byte [r0 + offsetof(zend_function, type)], 1
| mov FCARG1a, used_stack
| jnz >1
} else {
| mov FCARG1a, used_stack
}
| test byte [r0 + func_type_offset], 1
| mov FCARG1a, used_stack
| jnz >1
| // used_stack += (func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args)) * sizeof(zval);
| mov edx, opline->extended_value
if (!is_closure) {

View File

@@ -0,0 +1,32 @@
--TEST--
GH-17307 (Internal closure causes JIT failure)
--EXTENSIONS--
opcache
simplexml
bcmath
--INI--
opcache.jit=1254
opcache.jit_hot_func=1
opcache.jit_buffer_size=32M
--FILE--
<?php
$simple = new SimpleXMLElement("<root><a/><b/></root>");
function run_loop($firstTerms, $closure) {
foreach ($firstTerms as $firstTerm) {
\debug_zval_dump($firstTerm);
$closure($firstTerm, "10");
}
}
run_loop($simple, bcadd(...));
echo "Done\n";
?>
--EXPECTF--
object(SimpleXMLElement)#%d (0) refcount(3){
}
object(SimpleXMLElement)#%d (0) refcount(3){
}
Done