Skip to content

Commit

Permalink
Fixed bug #79917
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Aug 11, 2020
1 parent 183b853 commit 4609ded
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 34 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ PHP NEWS
- OPcache:
. Fixed bug #73060 (php failed with error after temp folder cleaned up).
(cmb)
. Fixed bug #79917 (File cache segfault with a static variable in inherited
method). (Nikita)

- Standard:
. Fixed bug #79930 (array_merge_recursive() crashes when called with array
Expand Down
80 changes: 46 additions & 34 deletions ext/opcache/zend_file_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,13 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
zend_file_cache_metainfo *info,
void *buf)
{
if (op_array->static_variables && !IS_SERIALIZED(op_array->static_variables)) {
/* Check whether this op_array has already been serialized. */
if (IS_SERIALIZED(op_array->opcodes)) {
ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
return;
}

if (op_array->static_variables) {
HashTable *ht;

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

if (op_array->scope && !IS_SERIALIZED(op_array->opcodes)) {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
} else {
SERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
}

if (op_array->scope) {
if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) {
op_array->refcount = (uint32_t*)(intptr_t)-1;
SERIALIZE_PTR(op_array->literals);
Expand All @@ -431,7 +444,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes);
}

if (op_array->literals && !IS_SERIALIZED(op_array->literals)) {
if (op_array->literals) {
zval *p, *end;

SERIALIZE_PTR(op_array->literals);
Expand All @@ -444,7 +457,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
}
}

if (!IS_SERIALIZED(op_array->opcodes)) {
{
zend_op *opline, *end;

#if !ZEND_USE_ABS_CONST_ADDR
Expand Down Expand Up @@ -552,13 +565,6 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
SERIALIZE_STR(op_array->doc_comment);
SERIALIZE_PTR(op_array->try_catch_array);
SERIALIZE_PTR(op_array->prototype);

ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
ZEND_MAP_PTR_INIT(op_array->run_time_cache, NULL);
} else {
SERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
}
}
}

Expand Down Expand Up @@ -1107,7 +1113,13 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
zend_persistent_script *script,
void *buf)
{
if (op_array->static_variables && !IS_UNSERIALIZED(op_array->static_variables)) {
/* Check whether this op_array has already been unserialized. */
if (IS_UNSERIALIZED(op_array->opcodes)) {
ZEND_ASSERT(op_array->scope && "Only method op_arrays should be shared");
return;
}

if (op_array->static_variables) {
HashTable *ht;

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

if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
if (op_array->static_variables) {
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
} else {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
}
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
} else {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (ZEND_MAP_PTR(op_array->run_time_cache)) {
if (script->corrupted) {
/* Not in SHM: Use serialized arena pointer. */
UNSERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
} else {
/* In SHM: Allocate new pointer. */
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
}
}
}

if (op_array->refcount) {
op_array->refcount = NULL;
UNSERIALIZE_PTR(op_array->literals);
Expand All @@ -1132,7 +1164,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
return;
}

if (op_array->literals && !IS_UNSERIALIZED(op_array->literals)) {
if (op_array->literals) {
zval *p, *end;

UNSERIALIZE_PTR(op_array->literals);
Expand All @@ -1144,7 +1176,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
}
}

if (!IS_UNSERIALIZED(op_array->opcodes)) {
{
zend_op *opline, *end;

UNSERIALIZE_PTR(op_array->opcodes);
Expand Down Expand Up @@ -1244,26 +1276,6 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
UNSERIALIZE_STR(op_array->doc_comment);
UNSERIALIZE_PTR(op_array->try_catch_array);
UNSERIALIZE_PTR(op_array->prototype);

if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
if (op_array->static_variables) {
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
} else {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
}
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
} else {
ZEND_MAP_PTR_INIT(op_array->static_variables_ptr, &op_array->static_variables);
if (ZEND_MAP_PTR(op_array->run_time_cache)) {
if (script->corrupted) {
/* Not in SHM: Use serialized arena pointer. */
UNSERIALIZE_PTR(ZEND_MAP_PTR(op_array->run_time_cache));
} else {
/* In SHM: Allocate new pointer. */
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
}
}
}
}
}

Expand Down

0 comments on commit 4609ded

Please sign in to comment.