diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-08-11 14:42:13 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-08-11 14:58:54 +0200 |
commit | 4609ded082fb5381bb39b408d471e88df9b81674 (patch) | |
tree | c75cea21c9cb083030a05fa45dad05066866e58e | |
parent | 183b853dc636883d4fb8134dcd39958dc628389e (diff) | |
download | php-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-- | NEWS | 2 | ||||
-rw-r--r-- | ext/opcache/zend_file_cache.c | 80 |
2 files changed, 48 insertions, 34 deletions
@@ -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); - } - } - } } } |