Skip to content

Commit 53f2aa9

Browse files
committed
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.
1 parent cb49400 commit 53f2aa9

File tree

5 files changed

+133
-29
lines changed

5 files changed

+133
-29
lines changed

‎NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ PHP NEWS
2828
warning and opline is not set yet). (nielsdos)
2929
. Fixed bug GH-14082 (Segmentation fault on unknown address 0x600000000018
3030
in ext/opcache/jit/zend_jit.c). (nielsdos)
31+
. Fixed bug GH-18898 (SEGV zend_jit_op_array_hot with property hooks
32+
and preloading). (nielsdos)
3133

3234
- PCNTL:
3335
. Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or

‎ext/opcache/jit/zend_jit.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3216,6 +3216,17 @@ int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
32163216
return FAILURE;
32173217
}
32183218

3219+
static void zend_jit_link_func_info(zend_op_array *op_array)
3220+
{
3221+
if (!ZEND_FUNC_INFO(op_array)) {
3222+
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
3223+
3224+
if (jit_extension) {
3225+
ZEND_SET_FUNC_INFO(op_array, jit_extension);
3226+
}
3227+
}
3228+
}
3229+
32193230
int zend_jit_script(zend_script *script)
32203231
{
32213232
void *checkpoint;
@@ -3303,6 +3314,7 @@ int zend_jit_script(zend_script *script)
33033314
zend_class_entry *ce;
33043315
zend_op_array *op_array;
33053316
zval *zv;
3317+
zend_property_info *prop;
33063318

33073319
ZEND_HASH_MAP_FOREACH_VAL(&script->class_table, zv) {
33083320
if (Z_TYPE_P(zv) == IS_ALIAS_PTR) {
@@ -3313,14 +3325,21 @@ int zend_jit_script(zend_script *script)
33133325
ZEND_ASSERT(ce->type == ZEND_USER_CLASS);
33143326

33153327
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
3316-
if (!ZEND_FUNC_INFO(op_array)) {
3317-
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
3328+
zend_jit_link_func_info(op_array);
3329+
} ZEND_HASH_FOREACH_END();
33183330

3319-
if (jit_extension) {
3320-
ZEND_SET_FUNC_INFO(op_array, jit_extension);
3331+
if (ce->num_hooked_props > 0) {
3332+
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
3333+
if (prop->hooks) {
3334+
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
3335+
if (prop->hooks[i]) {
3336+
op_array = &prop->hooks[i]->op_array;
3337+
zend_jit_link_func_info(op_array);
3338+
}
3339+
}
33213340
}
3322-
}
3323-
} ZEND_HASH_FOREACH_END();
3341+
} ZEND_HASH_FOREACH_END();
3342+
}
33243343
} ZEND_HASH_FOREACH_END();
33253344
}
33263345

‎ext/opcache/tests/jit/gh18898_1.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-18898 (SEGV zend_jit_op_array_hot with property hooks and preloading) - jit 1235
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.jit=1235
7+
opcache.jit_buffer_size=16M
8+
opcache.preload={PWD}/../gh18534_preload.inc
9+
--EXTENSIONS--
10+
opcache
11+
--SKIPIF--
12+
<?php
13+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
14+
?>
15+
--FILE--
16+
<?php
17+
$test = new DummyModel;
18+
var_dump($test->dummyProperty2);
19+
echo "ok";
20+
?>
21+
--EXPECT--
22+
NULL
23+
ok

‎ext/opcache/tests/jit/gh18898_2.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-18898 (SEGV zend_jit_op_array_hot with property hooks and preloading) - jit 1233
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.jit=1233
7+
opcache.jit_buffer_size=16M
8+
opcache.preload={PWD}/../gh18534_preload.inc
9+
--EXTENSIONS--
10+
opcache
11+
--SKIPIF--
12+
<?php
13+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
14+
?>
15+
--FILE--
16+
<?php
17+
$test = new DummyModel;
18+
var_dump($test->dummyProperty2);
19+
echo "ok";
20+
?>
21+
--EXPECT--
22+
NULL
23+
ok

‎ext/opcache/zend_persist.c

Lines changed: 60 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,39 @@ void zend_update_parent_ce(zend_class_entry *ce)
12621262
}
12631263
}
12641264

1265+
static void zend_accel_persist_jit_op_array(zend_op_array *op_array, zend_class_entry *ce)
1266+
{
1267+
if (op_array->type == ZEND_USER_FUNCTION) {
1268+
if (op_array->scope == ce
1269+
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)
1270+
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
1271+
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1272+
for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
1273+
zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1274+
}
1275+
}
1276+
}
1277+
}
1278+
1279+
static void zend_accel_persist_link_func_info(zend_op_array *op_array, zend_class_entry *ce)
1280+
{
1281+
if (op_array->type == ZEND_USER_FUNCTION
1282+
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
1283+
if ((op_array->scope != ce
1284+
|| (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
1285+
&& (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
1286+
|| JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
1287+
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
1288+
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
1289+
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
1290+
1291+
if (jit_extension) {
1292+
ZEND_SET_FUNC_INFO(op_array, jit_extension);
1293+
}
1294+
}
1295+
}
1296+
}
1297+
12651298
static void zend_accel_persist_class_table(HashTable *class_table)
12661299
{
12671300
Bucket *p;
@@ -1288,44 +1321,48 @@ static void zend_accel_persist_class_table(HashTable *class_table)
12881321
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
12891322
!ZCG(current_persistent_script)->corrupted) {
12901323
zend_op_array *op_array;
1324+
zend_property_info *prop;
12911325

12921326
ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
12931327
if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
12941328
ce = Z_PTR(p->val);
12951329
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
1296-
if (op_array->type == ZEND_USER_FUNCTION) {
1297-
if (op_array->scope == ce
1298-
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)
1299-
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
1300-
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1301-
for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
1302-
zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1330+
zend_accel_persist_jit_op_array(op_array, ce);
1331+
} ZEND_HASH_FOREACH_END();
1332+
1333+
if (ce->num_hooked_props > 0) {
1334+
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
1335+
if (prop->hooks) {
1336+
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
1337+
if (prop->hooks[i]) {
1338+
op_array = &prop->hooks[i]->op_array;
1339+
zend_accel_persist_jit_op_array(op_array, ce);
1340+
}
13031341
}
13041342
}
1305-
}
1306-
} ZEND_HASH_FOREACH_END();
1343+
} ZEND_HASH_FOREACH_END();
1344+
}
13071345
}
13081346
} ZEND_HASH_FOREACH_END();
13091347
ZEND_HASH_MAP_FOREACH_BUCKET(class_table, p) {
13101348
if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
13111349
ce = Z_PTR(p->val);
13121350
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, op_array) {
1313-
if (op_array->type == ZEND_USER_FUNCTION
1314-
&& !(op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
1315-
if ((op_array->scope != ce
1316-
|| (op_array->fn_flags & ZEND_ACC_TRAIT_CLONE))
1317-
&& (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
1318-
|| JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
1319-
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
1320-
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE)) {
1321-
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
1322-
1323-
if (jit_extension) {
1324-
ZEND_SET_FUNC_INFO(op_array, jit_extension);
1351+
zend_accel_persist_link_func_info(op_array, ce);
1352+
} ZEND_HASH_FOREACH_END();
1353+
1354+
if (ce->num_hooked_props > 0) {
1355+
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, prop) {
1356+
if (prop->hooks) {
1357+
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
1358+
if (prop->hooks[i]) {
1359+
op_array = &prop->hooks[i]->op_array;
1360+
zend_accel_persist_link_func_info(op_array, ce);
1361+
}
13251362
}
13261363
}
1327-
}
1328-
} ZEND_HASH_FOREACH_END();
1364+
} ZEND_HASH_FOREACH_END();
1365+
}
13291366
}
13301367
} ZEND_HASH_FOREACH_END();
13311368
}

0 commit comments

Comments
 (0)