mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-18898: SEGV zend_jit_op_array_hot with property hooks and preloading
Property hooks were not handled for JIT+trait+preloading. Split the existing functions that handle op arrays, and add iterations for property hooks. Closes GH-18923.
This commit is contained in:
2
NEWS
2
NEWS
@@ -28,6 +28,8 @@ PHP NEWS
|
||||
warning and opline is not set yet). (nielsdos)
|
||||
. Fixed bug GH-14082 (Segmentation fault on unknown address 0x600000000018
|
||||
in ext/opcache/jit/zend_jit.c). (nielsdos)
|
||||
. Fixed bug GH-18898 (SEGV zend_jit_op_array_hot with property hooks
|
||||
and preloading). (nielsdos)
|
||||
|
||||
- PCNTL:
|
||||
. Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or
|
||||
|
||||
@@ -3216,6 +3216,17 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static void zend_jit_link_func_info(zend_op_array *op_array)
|
||||
{
|
||||
if (!ZEND_FUNC_INFO(op_array)) {
|
||||
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
|
||||
|
||||
if (jit_extension) {
|
||||
ZEND_SET_FUNC_INFO(op_array, jit_extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int zend_jit_script(zend_script *script)
|
||||
{
|
||||
void *checkpoint;
|
||||
@@ -3303,6 +3314,7 @@ int zend_jit_script(zend_script *script)
|
||||
zend_class_entry *ce;
|
||||
zend_op_array *op_array;
|
||||
zval *zv;
|
||||
zend_property_info *prop;
|
||||
|
||||
ZEND_HASH_MAP_FOREACH_VAL(&script->class_table, zv) {
|
||||
if (Z_TYPE_P(zv) == IS_ALIAS_PTR) {
|
||||
@@ -3313,14 +3325,21 @@ int zend_jit_script(zend_script *script)
|
||||
ZEND_ASSERT(ce->type == ZEND_USER_CLASS);
|
||||
|
||||
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
|
||||
if (!ZEND_FUNC_INFO(op_array)) {
|
||||
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
|
||||
|
||||
if (jit_extension) {
|
||||
ZEND_SET_FUNC_INFO(op_array, jit_extension);
|
||||
}
|
||||
}
|
||||
zend_jit_link_func_info(op_array);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (ce->num_hooked_props > 0) {
|
||||
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
|
||||
if (prop->hooks) {
|
||||
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
|
||||
if (prop->hooks[i]) {
|
||||
op_array = &prop->hooks[i]->op_array;
|
||||
zend_jit_link_func_info(op_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
|
||||
23
ext/opcache/tests/jit/gh18898_1.phpt
Normal file
23
ext/opcache/tests/jit/gh18898_1.phpt
Normal file
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
GH-18898 (SEGV zend_jit_op_array_hot with property hooks and preloading) - jit 1235
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.jit=1235
|
||||
opcache.jit_buffer_size=16M
|
||||
opcache.preload={PWD}/../gh18534_preload.inc
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$test = new DummyModel;
|
||||
var_dump($test->dummyProperty2);
|
||||
echo "ok";
|
||||
?>
|
||||
--EXPECT--
|
||||
NULL
|
||||
ok
|
||||
23
ext/opcache/tests/jit/gh18898_2.phpt
Normal file
23
ext/opcache/tests/jit/gh18898_2.phpt
Normal file
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
GH-18898 (SEGV zend_jit_op_array_hot with property hooks and preloading) - jit 1233
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.jit=1233
|
||||
opcache.jit_buffer_size=16M
|
||||
opcache.preload={PWD}/../gh18534_preload.inc
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$test = new DummyModel;
|
||||
var_dump($test->dummyProperty2);
|
||||
echo "ok";
|
||||
?>
|
||||
--EXPECT--
|
||||
NULL
|
||||
ok
|
||||
@@ -1262,6 +1262,39 @@ void zend_update_parent_ce(zend_class_entry *ce)
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_accel_persist_jit_op_array(zend_op_array *op_array, zend_class_entry *ce)
|
||||
{
|
||||
if (op_array->type == ZEND_USER_FUNCTION) {
|
||||
if (op_array->scope == ce
|
||||
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)
|
||||
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
|
||||
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
|
||||
for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
|
||||
zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_accel_persist_link_func_info(zend_op_array *op_array, zend_class_entry *ce)
|
||||
{
|
||||
if (op_array->type == ZEND_USER_FUNCTION
|
||||
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
|
||||
if ((op_array->scope != ce
|
||||
|| (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
|
||||
&& (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
|
||||
|| JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
|
||||
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
|
||||
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
|
||||
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
|
||||
|
||||
if (jit_extension) {
|
||||
ZEND_SET_FUNC_INFO(op_array, jit_extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_accel_persist_class_table(HashTable *class_table)
|
||||
{
|
||||
Bucket *p;
|
||||
@@ -1288,44 +1321,48 @@ static void zend_accel_persist_class_table(HashTable *class_table)
|
||||
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
|
||||
!ZCG(current_persistent_script)->corrupted) {
|
||||
zend_op_array *op_array;
|
||||
zend_property_info *prop;
|
||||
|
||||
ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
|
||||
if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
|
||||
ce = Z_PTR(p->val);
|
||||
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
|
||||
if (op_array->type == ZEND_USER_FUNCTION) {
|
||||
if (op_array->scope == ce
|
||||
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)
|
||||
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
|
||||
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
|
||||
for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
|
||||
zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
|
||||
zend_accel_persist_jit_op_array(op_array, ce);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (ce->num_hooked_props > 0) {
|
||||
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
|
||||
if (prop->hooks) {
|
||||
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
|
||||
if (prop->hooks[i]) {
|
||||
op_array = &prop->hooks[i]->op_array;
|
||||
zend_accel_persist_jit_op_array(op_array, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
|
||||
if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
|
||||
ce = Z_PTR(p->val);
|
||||
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
|
||||
if (op_array->type == ZEND_USER_FUNCTION
|
||||
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
|
||||
if ((op_array->scope != ce
|
||||
|| (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
|
||||
&& (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
|
||||
|| JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
|
||||
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
|
||||
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
|
||||
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
|
||||
zend_accel_persist_link_func_info(op_array, ce);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (jit_extension) {
|
||||
ZEND_SET_FUNC_INFO(op_array, jit_extension);
|
||||
if (ce->num_hooked_props > 0) {
|
||||
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
|
||||
if (prop->hooks) {
|
||||
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
|
||||
if (prop->hooks[i]) {
|
||||
op_array = &prop->hooks[i]->op_array;
|
||||
zend_accel_persist_link_func_info(op_array, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user