summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-08-11 14:42:13 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-08-11 14:58:54 +0200
commit4609ded082fb5381bb39b408d471e88df9b81674 (patch)
treec75cea21c9cb083030a05fa45dad05066866e58e
parent183b853dc636883d4fb8134dcd39958dc628389e (diff)
downloadphp-git-4609ded082fb5381bb39b408d471e88df9b81674.tar.gz
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.
-rw-r--r--NEWS2
-rw-r--r--ext/opcache/zend_file_cache.c80
2 files changed, 48 insertions, 34 deletions
diff --git a/NEWS b/NEWS
index 1063e5772b..73ad884963 100644
--- a/NEWS
+++ b/NEWS
@@ -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
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 8edd70a256..41b3325795 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -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);
@@ -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);
@@ -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);
@@ -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
@@ -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));
- }
}
}
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
- }
- }
- }
}
}