From 9ae784d48998c7d9872bd53dc170a6ff599cfd17 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Thu, 28 Jul 2022 22:54:52 +0200 Subject: [PATCH] Extended map_ptr before copying class table --- Zend/zend_types.h | 1 + ext/opcache/tests/gh9164.phpt | 46 +++++++++++++++++++++++ ext/opcache/zend_accelerator_util_funcs.c | 22 +++++------ 3 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 ext/opcache/tests/gh9164.phpt diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 85a768c3da1ef..df64541749d4c 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -743,6 +743,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #define ZSTR_SET_CE_CACHE_EX(s, ce, validate) do { \ if (!(validate) || ZSTR_VALID_CE_CACHE(s)) { \ + ZEND_ASSERT((validate) || ZSTR_VALID_CE_CACHE(s)); \ SET_CE_CACHE(GC_REFCOUNT(s), ce); \ } \ } while (0) diff --git a/ext/opcache/tests/gh9164.phpt b/ext/opcache/tests/gh9164.phpt new file mode 100644 index 0000000000000..c401639d3314e --- /dev/null +++ b/ext/opcache/tests/gh9164.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug GH-9164: Segfault in zend_accel_class_hash_copy +--EXTENSIONS-- +opcache +pcntl +--INI-- +opcache.enable_cli=1 +--FILE-- + 0) { + pcntl_wait($status); + // Ensure that file has been cached. If not, this is testing nothing anymore. + if (!isset(opcache_get_status()['scripts'][$incfile])) { + print "File not cached\n"; + } + // Populates local cache + require $incfile; + var_dump(new FooBar4095); + unlink($incfile); +} else { + echo "pcntl_fork() failed\n"; +} + +?> +--EXPECTF-- +object(FooBar4095)#%d (0) { +} diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 28b458235c4e0..6a454a0a9e447 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -347,15 +347,11 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); *op_array = persistent_script->script.main_op_array; - if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) { - zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table); - } - - if (zend_hash_num_elements(&persistent_script->script.class_table) > 0) { - zend_accel_class_hash_copy(CG(class_table), &persistent_script->script.class_table); - } - if (EXPECTED(from_shared_memory)) { + if (ZCSG(map_ptr_last) > CG(map_ptr_last)) { + zend_map_ptr_extend(ZCSG(map_ptr_last)); + } + /* Register __COMPILER_HALT_OFFSET__ constant */ if (persistent_script->compiler_halt_offset != 0 && persistent_script->script.filename) { @@ -368,10 +364,14 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script, } zend_string_release_ex(name, 0); } + } - if (ZCSG(map_ptr_last) > CG(map_ptr_last)) { - zend_map_ptr_extend(ZCSG(map_ptr_last)); - } + if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) { + zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table); + } + + if (zend_hash_num_elements(&persistent_script->script.class_table) > 0) { + zend_accel_class_hash_copy(CG(class_table), &persistent_script->script.class_table); } if (persistent_script->num_early_bindings) {