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:
3
NEWS
3
NEWS
@@ -25,6 +25,9 @@ PHP NEWS
|
|||||||
- Intl:
|
- Intl:
|
||||||
. Fixed bug GH-11874 (intl causing segfault in docker images). (nielsdos)
|
. Fixed bug GH-11874 (intl causing segfault in docker images). (nielsdos)
|
||||||
|
|
||||||
|
- Opcache:
|
||||||
|
. Fixed bug GH-17307 (Internal closure causes JIT failure). (nielsdos)
|
||||||
|
|
||||||
- PHPDBG:
|
- PHPDBG:
|
||||||
. Fix crashes in function registration + test. (nielsdos, Girgias)
|
. Fix crashes in function registration + test. (nielsdos, Girgias)
|
||||||
|
|
||||||
|
|||||||
@@ -8471,6 +8471,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
|
|||||||
{
|
{
|
||||||
uint32_t used_stack;
|
uint32_t used_stack;
|
||||||
bool stack_check = 1;
|
bool stack_check = 1;
|
||||||
|
const size_t func_type_offset = is_closure ? offsetof(zend_closure, func.type) : offsetof(zend_function, type);
|
||||||
|
|
||||||
// REG0 -> zend_function
|
// REG0 -> zend_function
|
||||||
// FCARG1 -> used_stack
|
// 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);
|
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value + ZEND_OBSERVER_ENABLED) * sizeof(zval);
|
||||||
|
|
||||||
| // if (EXPECTED(ZEND_USER_CODE(func->type))) {
|
| // if (EXPECTED(ZEND_USER_CODE(func->type))) {
|
||||||
if (!is_closure) {
|
| LOAD_32BIT_VAL FCARG1w, used_stack
|
||||||
| LOAD_32BIT_VAL FCARG1w, used_stack
|
| // Check whether REG0 is an internal function.
|
||||||
| // Check whether REG0 is an internal function.
|
| ldrb TMP1w, [REG0, #func_type_offset]
|
||||||
| ldrb TMP1w, [REG0, #offsetof(zend_function, type)]
|
| TST_32_WITH_CONST TMP1w, 1, TMP2w
|
||||||
| TST_32_WITH_CONST TMP1w, 1, TMP2w
|
| bne >1
|
||||||
| bne >1
|
|
||||||
} else {
|
|
||||||
| LOAD_32BIT_VAL FCARG1w, used_stack
|
|
||||||
}
|
|
||||||
| // used_stack += (func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args)) * sizeof(zval);
|
| // 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
|
| LOAD_32BIT_VAL REG2w, opline->extended_value
|
||||||
if (!is_closure) {
|
if (!is_closure) {
|
||||||
|
|||||||
@@ -9072,6 +9072,7 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
|
|||||||
{
|
{
|
||||||
uint32_t used_stack;
|
uint32_t used_stack;
|
||||||
bool stack_check = 1;
|
bool stack_check = 1;
|
||||||
|
const size_t func_type_offset = is_closure ? offsetof(zend_closure, func.type) : offsetof(zend_function, type);
|
||||||
|
|
||||||
if (func) {
|
if (func) {
|
||||||
used_stack = zend_vm_calc_used_stack(opline->extended_value, 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);
|
used_stack = (ZEND_CALL_FRAME_SLOT + opline->extended_value + ZEND_OBSERVER_ENABLED) * sizeof(zval);
|
||||||
|
|
||||||
| // if (EXPECTED(ZEND_USER_CODE(func->type))) {
|
| // if (EXPECTED(ZEND_USER_CODE(func->type))) {
|
||||||
if (!is_closure) {
|
| test byte [r0 + func_type_offset], 1
|
||||||
| test byte [r0 + offsetof(zend_function, type)], 1
|
| mov FCARG1a, used_stack
|
||||||
| mov FCARG1a, used_stack
|
| jnz >1
|
||||||
| jnz >1
|
|
||||||
} else {
|
|
||||||
| mov FCARG1a, used_stack
|
|
||||||
}
|
|
||||||
| // used_stack += (func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args)) * sizeof(zval);
|
| // 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
|
| mov edx, opline->extended_value
|
||||||
if (!is_closure) {
|
if (!is_closure) {
|
||||||
|
|||||||
32
ext/opcache/tests/jit/gh17307.phpt
Normal file
32
ext/opcache/tests/jit/gh17307.phpt
Normal 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
|
||||||
Reference in New Issue
Block a user