Skip to content

Commit 4609ded

Browse files
committed
Fixed bug #79917
op_arrays can be shared on two levels: Either the op_array is completely shared, or it is distinct but shares all members (apart from static_variables). The the op_array is distinct, we need to make sure to properly initialize the MAP_PTR structures.
1 parent 183b853 commit 4609ded

File tree

2 files changed

+48
-34
lines changed

2 files changed

+48
-34
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ PHP NEWS
2828
- OPcache:
2929
. Fixed bug #73060 (php failed with error after temp folder cleaned up).
3030
(cmb)
31+
. Fixed bug #79917 (File cache segfault with a static variable in inherited
32+
method). (Nikita)
3133

3234
- Standard:
3335
. Fixed bug #79930 (array_merge_recursive() crashes when called with array

ext/opcache/zend_file_cache.c

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,13 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
403403
zend_file_cache_metainfo *info,
404404
void *buf)
405405
{
406-
if (op_array->static_variables && !IS_SERIALIZED(op_array->static_variables)) {
406+
/* Check whether this op_array has already been serialized. */
407+
if (IS_SERIALIZED(op_array->opcodes)) {
408+
ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
409+
return;
410+
}
411+
412+
if (op_array->static_variables) {
407413
HashTable *ht;
408414

409415
SERIALIZE_PTR(op_array->static_variables);
@@ -412,7 +418,14 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
412418
zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval);
413419
}
414420

415-
if (op_array->scope && !IS_SERIALIZED(op_array->opcodes)) {
421+
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
422+
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
423+
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
424+
} else {
425+
SERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
426+
}
427+
428+
if (op_array->scope) {
416429
if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
417430
op_array->refcount = (uint32_t*)(intptr_t)-1;
418431
SERIALIZE_PTR(op_array->literals);
@@ -431,7 +444,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
431444
zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes);
432445
}
433446

434-
if (op_array->literals && !IS_SERIALIZED(op_array->literals)) {
447+
if (op_array->literals) {
435448
zval *p, *end;
436449

437450
SERIALIZE_PTR(op_array->literals);
@@ -444,7 +457,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
444457
}
445458
}
446459

447-
if (!IS_SERIALIZED(op_array->opcodes)) {
460+
{
448461
zend_op *opline, *end;
449462

450463
#if !ZEND_USE_ABS_CONST_ADDR
@@ -552,13 +565,6 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
552565
SERIALIZE_STR(op_array->doc_comment);
553566
SERIALIZE_PTR(op_array->try_catch_array);
554567
SERIALIZE_PTR(op_array->prototype);
555-
556-
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
557-
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
558-
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
559-
} else {
560-
SERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
561-
}
562568
}
563569
}
564570

@@ -1107,7 +1113,13 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
11071113
zend_persistent_script *script,
11081114
void *buf)
11091115
{
1110-
if (op_array->static_variables && !IS_UNSERIALIZED(op_array->static_variables)) {
1116+
/* Check whether this op_array has already been unserialized. */
1117+
if (IS_UNSERIALIZED(op_array->opcodes)) {
1118+
ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
1119+
return;
1120+
}
1121+
1122+
if (op_array->static_variables) {
11111123
HashTable *ht;
11121124

11131125
UNSERIALIZE_PTR(op_array->static_variables);
@@ -1116,6 +1128,26 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
11161128
script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR);
11171129
}
11181130

1131+
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
1132+
if (op_array->static_variables) {
1133+
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
1134+
} else {
1135+
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
1136+
}
1137+
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
1138+
} else {
1139+
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
1140+
if (ZEND_MAP_PTR(op_array->run_time_cache)) {
1141+
if (script->corrupted) {
1142+
/* Not in SHM: Use serialized arena pointer. */
1143+
UNSERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
1144+
} else {
1145+
/* In SHM: Allocate new pointer. */
1146+
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
1147+
}
1148+
}
1149+
}
1150+
11191151
if (op_array->refcount) {
11201152
op_array->refcount = NULL;
11211153
UNSERIALIZE_PTR(op_array->literals);
@@ -1132,7 +1164,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
11321164
return;
11331165
}
11341166

1135-
if (op_array->literals && !IS_UNSERIALIZED(op_array->literals)) {
1167+
if (op_array->literals) {
11361168
zval *p, *end;
11371169

11381170
UNSERIALIZE_PTR(op_array->literals);
@@ -1144,7 +1176,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
11441176
}
11451177
}
11461178

1147-
if (!IS_UNSERIALIZED(op_array->opcodes)) {
1179+
{
11481180
zend_op *opline, *end;
11491181

11501182
UNSERIALIZE_PTR(op_array->opcodes);
@@ -1244,26 +1276,6 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
12441276
UNSERIALIZE_STR(op_array->doc_comment);
12451277
UNSERIALIZE_PTR(op_array->try_catch_array);
12461278
UNSERIALIZE_PTR(op_array->prototype);
1247-
1248-
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
1249-
if (op_array->static_variables) {
1250-
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
1251-
} else {
1252-
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
1253-
}
1254-
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
1255-
} else {
1256-
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
1257-
if (ZEND_MAP_PTR(op_array->run_time_cache)) {
1258-
if (script->corrupted) {
1259-
/* Not in SHM: Use serialized arena pointer. */
1260-
UNSERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
1261-
} else {
1262-
/* In SHM: Allocate new pointer. */
1263-
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
1264-
}
1265-
}
1266-
}
12671279
}
12681280
}
12691281

0 commit comments

Comments
 (0)