Skip to content

Commit cb0854b

Browse files
committed
JIT class methods only when class entry is completely persistent.
This fixes a number of test failures on low optimization levels. (e.g. use after free in Zend/tests/bug54268.phpt and tests/classes/protected_001.phpt with opcache.jit=1204)
1 parent 4fe07d4 commit cb0854b

File tree

1 file changed

+47
-22
lines changed

1 file changed

+47
-22
lines changed

ext/opcache/zend_persist.c

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -485,21 +485,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
485485
ZEND_ASSERT(op_array->vars != NULL);
486486
}
487487
ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
488-
#ifdef HAVE_JIT
489-
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
490-
!ZCG(current_persistent_script)->corrupted) {
491-
if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
492-
|| JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
493-
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
494-
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
495-
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
496-
497-
if (jit_extension) {
498-
ZEND_SET_FUNC_INFO(op_array, jit_extension);
499-
}
500-
}
501-
}
502-
#endif
503488
return;
504489
}
505490
} else {
@@ -700,13 +685,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
700685
}
701686

702687
ZCG(mem) = (void*)((char*)ZCG(mem) + ZEND_ALIGNED_SIZE(zend_extensions_op_array_persist(op_array, ZCG(mem))));
703-
704-
#ifdef HAVE_JIT
705-
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
706-
!ZCG(current_persistent_script)->corrupted) {
707-
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
708-
}
709-
#endif
710688
}
711689

712690
static void zend_persist_op_array(zval *zv)
@@ -726,6 +704,11 @@ static void zend_persist_op_array(zval *zv)
726704
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
727705
}
728706
}
707+
#ifdef HAVE_JIT
708+
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
709+
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
710+
}
711+
#endif
729712
} else {
730713
/* This can happen during preloading, if a dynamic function definition is declared. */
731714
Z_PTR_P(zv) = old_op_array;
@@ -1253,7 +1236,11 @@ static void zend_accel_persist_class_table(HashTable *class_table)
12531236
{
12541237
Bucket *p;
12551238
zend_class_entry *ce;
1239+
#ifdef HAVE_JIT
1240+
bool orig_jit_on = JIT_G(on);
12561241

1242+
JIT_G(on) = 0;
1243+
#endif
12571244
zend_hash_persist(class_table);
12581245
ZEND_HASH_FOREACH_BUCKET(class_table, p) {
12591246
ZEND_ASSERT(p->key != NULL);
@@ -1266,6 +1253,39 @@ static void zend_accel_persist_class_table(HashTable *class_table)
12661253
zend_update_parent_ce(ce);
12671254
}
12681255
} ZEND_HASH_FOREACH_END();
1256+
#ifdef HAVE_JIT
1257+
JIT_G(on) = orig_jit_on;
1258+
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS &&
1259+
!ZCG(current_persistent_script)->corrupted) {
1260+
zend_op_array *op_array;
1261+
1262+
ZEND_HASH_FOREACH_BUCKET(class_table, p) {
1263+
if (EXPECTED(Z_TYPE(p->val) != IS_ALIAS_PTR)) {
1264+
ce = Z_PTR(p->val);
1265+
ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
1266+
if (op_array->type == ZEND_USER_FUNCTION) {
1267+
if (op_array->scope == ce
1268+
&& !(op_array->fn_flags & ZEND_ACC_TRAIT_CLONE)) {
1269+
zend_jit_op_array(op_array, ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1270+
for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
1271+
zend_jit_op_array(op_array->dynamic_func_defs[i], ZCG(current_persistent_script) ? &ZCG(current_persistent_script)->script : NULL);
1272+
}
1273+
} else if (JIT_G(trigger) == ZEND_JIT_ON_FIRST_EXEC
1274+
|| JIT_G(trigger) == ZEND_JIT_ON_PROF_REQUEST
1275+
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_COUNTERS
1276+
|| JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
1277+
void *jit_extension = zend_shared_alloc_get_xlat_entry(op_array->opcodes);
1278+
1279+
if (jit_extension) {
1280+
ZEND_SET_FUNC_INFO(op_array, jit_extension);
1281+
}
1282+
}
1283+
}
1284+
} ZEND_HASH_FOREACH_END();
1285+
}
1286+
} ZEND_HASH_FOREACH_END();
1287+
}
1288+
#endif
12691289
}
12701290

12711291
zend_error_info **zend_persist_warnings(uint32_t num_warnings, zend_error_info **warnings) {
@@ -1327,6 +1347,11 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
13271347
if (script->script.main_op_array.static_variables) {
13281348
ZEND_MAP_PTR_NEW(script->script.main_op_array.static_variables_ptr);
13291349
}
1350+
#ifdef HAVE_JIT
1351+
if (JIT_G(on) && JIT_G(opt_level) <= ZEND_JIT_LEVEL_OPT_FUNCS) {
1352+
zend_jit_op_array(&script->script.main_op_array, &script->script);
1353+
}
1354+
#endif
13301355
}
13311356
script->warnings = zend_persist_warnings(script->num_warnings, script->warnings);
13321357

0 commit comments

Comments
 (0)