mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug 78175 (Preloading must store default values of static variables and properties)
This commit is contained in:
commit
e18c60cd8d
11 changed files with 127 additions and 16 deletions
|
@ -5768,8 +5768,14 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
|
|||
|
||||
init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
|
||||
|
||||
ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
|
||||
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
|
||||
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
|
||||
op_array->fn_flags |= ZEND_ACC_PRELOADED;
|
||||
ZEND_MAP_PTR_NEW(op_array->run_time_cache);
|
||||
ZEND_MAP_PTR_NEW(op_array->static_variables_ptr);
|
||||
} else {
|
||||
ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
|
||||
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
|
||||
}
|
||||
|
||||
op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
|
||||
op_array->fn_flags |= decl->flags;
|
||||
|
@ -6204,6 +6210,11 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
|
|||
ce->name = name;
|
||||
zend_initialize_class_data(ce, 1);
|
||||
|
||||
if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
|
||||
ce->ce_flags |= ZEND_ACC_PRELOADED;
|
||||
ZEND_MAP_PTR_NEW(ce->static_members_table);
|
||||
}
|
||||
|
||||
ce->ce_flags |= decl->flags;
|
||||
ce->info.user.filename = zend_get_compiled_filename();
|
||||
ce->info.user.line_start = decl->start_lineno;
|
||||
|
|
|
@ -1151,7 +1151,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
|||
} while (dst != end);
|
||||
} else if (ce->type == ZEND_USER_CLASS) {
|
||||
if (CE_STATIC_MEMBERS(parent_ce) == NULL) {
|
||||
ZEND_ASSERT(parent_ce->ce_flags & ZEND_ACC_IMMUTABLE);
|
||||
ZEND_ASSERT(parent_ce->ce_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED));
|
||||
zend_class_init_statics(parent_ce);
|
||||
}
|
||||
src = CE_STATIC_MEMBERS(parent_ce) + parent_ce->default_static_members_count;
|
||||
|
|
|
@ -1446,7 +1446,7 @@ ZEND_API zval *zend_std_get_static_property_with_info(zend_class_entry *ce, zend
|
|||
|
||||
/* check if static properties were destroyed */
|
||||
if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
|
||||
if (ce->type == ZEND_INTERNAL_CLASS || (ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
|
||||
if (ce->type == ZEND_INTERNAL_CLASS || (ce->ce_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED))) {
|
||||
zend_class_init_statics(ce);
|
||||
} else {
|
||||
undeclared_property:
|
||||
|
|
|
@ -219,7 +219,7 @@ ZEND_API void destroy_zend_class(zval *zv)
|
|||
zend_class_entry *ce = Z_PTR_P(zv);
|
||||
zend_function *fn;
|
||||
|
||||
if (ce->ce_flags & ZEND_ACC_IMMUTABLE) {
|
||||
if (ce->ce_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED)) {
|
||||
zend_op_array *op_array;
|
||||
|
||||
if (ce->default_static_members_count) {
|
||||
|
|
|
@ -8224,7 +8224,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
|
|||
|
||||
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
|
||||
if (!ht) {
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED));
|
||||
ht = zend_array_dup(EX(func)->op_array.static_variables);
|
||||
ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
|
||||
} else if (GC_REFCOUNT(ht) > 1) {
|
||||
|
|
|
@ -48927,7 +48927,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN
|
|||
|
||||
ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
|
||||
if (!ht) {
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
|
||||
ZEND_ASSERT(EX(func)->op_array.fn_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED));
|
||||
ht = zend_array_dup(EX(func)->op_array.static_variables);
|
||||
ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
|
||||
} else if (GC_REFCOUNT(ht) > 1) {
|
||||
|
|
|
@ -3230,7 +3230,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);
|
||||
}
|
||||
|
@ -3264,15 +3263,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);
|
||||
}
|
||||
|
@ -3535,6 +3526,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 {
|
||||
|
@ -3706,6 +3698,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);
|
||||
|
@ -4060,6 +4059,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;
|
||||
|
@ -4076,6 +4077,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;
|
||||
|
@ -4159,10 +4162,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();
|
||||
|
@ -4288,6 +4339,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:
|
||||
|
|
19
ext/opcache/tests/bug78175_2.phpt
Normal file
19
ext/opcache/tests/bug78175_2.phpt
Normal file
|
@ -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
|
20
ext/opcache/tests/preload_bug78175_2.inc
Normal file
20
ext/opcache/tests/preload_bug78175_2.inc
Normal file
|
@ -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();
|
|
@ -251,6 +251,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue