diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2019-06-24 20:32:27 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2019-06-24 20:32:27 +0300 |
| commit | 0f29fb5cd81d9df4829bc63f704019df910b3075 (patch) | |
| tree | 05c34dda76c2e45630d5fe9528d10dc5fef97bd3 /ext | |
| parent | 94df6dc3fd07fa187ba09c587a8d1357fd8bbe6f (diff) | |
| download | php-git-0f29fb5cd81d9df4829bc63f704019df910b3075.tar.gz | |
Fixed bug 78175 (Preloading must store default values of static variables and properties)
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/opcache/ZendAccelerator.c | 71 | ||||
| -rw-r--r-- | ext/opcache/tests/bug78175_2.phpt | 19 | ||||
| -rw-r--r-- | ext/opcache/tests/preload_bug78175_2.inc | 20 | ||||
| -rw-r--r-- | ext/opcache/zend_persist.c | 4 | ||||
| -rw-r--r-- | ext/opcache/zend_persist_calc.c | 4 |
5 files changed, 109 insertions, 9 deletions
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index c8f640bfeb..60e44c6508 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -3176,7 +3176,6 @@ static void preload_move_user_functions(HashTable *src, HashTable *dst) } if (copy) { _zend_hash_append_ptr(dst, p->key, function); - function->common.fn_flags |= ZEND_ACC_PRELOADED; } else { orig_dtor(&p->val); } @@ -3210,15 +3209,7 @@ static void preload_move_user_classes(HashTable *src, HashTable *dst) } } if (copy) { - zend_function *function; - - ce->ce_flags |= ZEND_ACC_PRELOADED; _zend_hash_append_ptr(dst, p->key, ce); - ZEND_HASH_FOREACH_PTR(&ce->function_table, function) { - if (EXPECTED(function->type == ZEND_USER_FUNCTION)) { - function->common.fn_flags |= ZEND_ACC_PRELOADED; - } - } ZEND_HASH_FOREACH_END(); } else { orig_dtor(&p->val); } @@ -3481,6 +3472,7 @@ static void preload_link(void) uint32_t i; zend_op_array *op_array; dtor_func_t orig_dtor; + zend_function *function; /* Resolve class dependencies */ do { @@ -3652,6 +3644,13 @@ static void preload_link(void) } else { continue; } + ce->ce_flags &= ~ZEND_ACC_PRELOADED; + ZEND_HASH_FOREACH_PTR(&ce->function_table, function) { + if (EXPECTED(function->type == ZEND_USER_FUNCTION) + && function->common.scope == ce) { + function->common.fn_flags &= ~ZEND_ACC_PRELOADED; + } + } ZEND_HASH_FOREACH_END(); script = zend_hash_find_ptr(preload_scripts, ce->info.user.filename); ZEND_ASSERT(script); zend_hash_add(&script->script.class_table, key, zv); @@ -4006,6 +4005,8 @@ static int accel_preload(const char *config) int ret; uint32_t orig_compiler_options; char *orig_open_basedir; + size_t orig_map_ptr_last; + zval *zv; ZCG(enabled) = 0; ZCG(accelerator_enabled) = 0; @@ -4022,6 +4023,8 @@ static int accel_preload(const char *config) CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION; // CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES; + orig_map_ptr_last = CG(map_ptr_last); + /* Compile and execute proloading script */ memset(&file_handle, 0, sizeof(file_handle)); file_handle.filename = (char*)config; @@ -4105,10 +4108,58 @@ static int accel_preload(const char *config) zend_objects_store_free_object_storage(&EG(objects_store), 1); + /* Cleanup static variables of preloaded functions */ + ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) { + zend_op_array *op_array = Z_PTR_P(zv); + if (op_array->type == ZEND_INTERNAL_FUNCTION) { + break; + } + ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_PRELOADED); + if (op_array->static_variables) { + HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr); + if (ht) { + ZEND_ASSERT(GC_REFCOUNT(ht) == 1); + zend_array_destroy(ht); + ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL); + } + } + } ZEND_HASH_FOREACH_END(); + + /* Cleanup static properties and variables of preloaded classes */ + ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) { + zend_class_entry *ce = Z_PTR_P(zv); + if (ce->type == ZEND_INTERNAL_CLASS) { + break; + } + ZEND_ASSERT(ce->ce_flags & ZEND_ACC_PRELOADED); + if (ce->default_static_members_count) { + zend_cleanup_internal_class_data(ce); + } + if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { + zend_op_array *op_array; + + ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) { + if (op_array->type == ZEND_USER_FUNCTION) { + if (op_array->static_variables) { + HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr); + if (ht) { + ZEND_ASSERT(GC_REFCOUNT(ht) == 1); + zend_array_destroy(ht); + ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL); + } + } + } + } ZEND_HASH_FOREACH_END(); + } + } ZEND_HASH_FOREACH_END(); + + CG(map_ptr_last) = orig_map_ptr_last; + /* Inheritance errors may be thrown during linking */ zend_try { preload_link(); } zend_catch { + CG(map_ptr_last) = orig_map_ptr_last; ret = FAILURE; goto finish; } zend_end_try(); @@ -4234,6 +4285,8 @@ static int accel_preload(const char *config) HANDLE_UNBLOCK_INTERRUPTIONS(); zend_shared_alloc_destroy_xlat_table(); + } else { + CG(map_ptr_last) = orig_map_ptr_last; } finish: diff --git a/ext/opcache/tests/bug78175_2.phpt b/ext/opcache/tests/bug78175_2.phpt new file mode 100644 index 0000000000..1d736f6e10 --- /dev/null +++ b/ext/opcache/tests/bug78175_2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #78175.2 (Preloading segfaults at preload time and at runtime) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +opcache.preload={PWD}/preload_bug78175_2.inc +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +var_dump(get_class(Loader::getLoader())); +var_dump(Loader::getCounter()); +?> +OK +--EXPECT-- +string(6) "Loader" +int(0) +OK diff --git a/ext/opcache/tests/preload_bug78175_2.inc b/ext/opcache/tests/preload_bug78175_2.inc new file mode 100644 index 0000000000..288c142678 --- /dev/null +++ b/ext/opcache/tests/preload_bug78175_2.inc @@ -0,0 +1,20 @@ +<?php +class Loader { + static private $loader; + + static function getLoader() { + if (null !== self::$loader) { + return self::$loader; + } + return self::$loader = new Loader(); + } + + static function getCounter() { + static $counter = 0; + return $counter++; + } +} + +Loader::getLoader(); +Loader::getCounter(); +Loader::getCounter(); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index f5e1c45738..698611e1a7 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -247,6 +247,10 @@ static void zend_persist_zval(zval *z) efree(old_ref); } break; + default: + ZEND_ASSERT(Z_TYPE_P(z) != IS_OBJECT); + ZEND_ASSERT(Z_TYPE_P(z) != IS_RESOURCE); + break; } } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index ca96da7ffa..a38398e3cf 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -141,6 +141,10 @@ static void zend_persist_zval_calc(zval *z) zend_persist_ast_calc(Z_ASTVAL_P(z)); } break; + default: + ZEND_ASSERT(Z_TYPE_P(z) != IS_OBJECT); + ZEND_ASSERT(Z_TYPE_P(z) != IS_RESOURCE); + break; } } |
