Skip to content

Commit

Permalink
Backport fix GH-17307
Browse files Browse the repository at this point in the history
This is a backport of GH-17319 to fix GH-17307 on lower branches.

Closes GH-17424.
  • Loading branch information
nielsdos committed Jan 10, 2025
1 parent a2a7287 commit e8fce29
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 16 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
15 changes: 6 additions & 9 deletions ext/opcache/jit/zend_jit_arm64.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand Down
11 changes: 4 additions & 7 deletions ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand Down
32 changes: 32 additions & 0 deletions ext/opcache/tests/jit/gh17307.phpt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit e8fce29

Please sign in to comment.