summaryrefslogtreecommitdiff
path: root/Zend/zend_inheritance.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-02-17 10:47:30 +0100
committerNikita Popov <nikita.ppv@gmail.com>2021-02-18 11:18:19 +0100
commit5d160e309ed207e618d49029e51c9c2dc2c5e61c (patch)
treea6f1deb6f582e42792a8dccedb117a26decd3e65 /Zend/zend_inheritance.c
parente03284739f4a3a1052dfe5497fbf06c1b206f895 (diff)
downloadphp-git-5d160e309ed207e618d49029e51c9c2dc2c5e61c.tar.gz
Fix static variable behavior with inheritance
When a method is inherited, the static variables will now always use the initial values, rather than the values at the time of inheritance. As such, behavior no longer depends on whether inheritance happens before or after a method has been called. This is implemented by always keeping static_variables as the original values, and static_variables_ptr as the modified copy. Closes GH-6705.
Diffstat (limited to 'Zend/zend_inheritance.c')
-rw-r--r--Zend/zend_inheritance.c39
1 files changed, 15 insertions, 24 deletions
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index 2c0b7a9f64..75f5536eaa 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -89,28 +89,10 @@ static zend_function *zend_duplicate_internal_function(zend_function *func, zend
static zend_function *zend_duplicate_user_function(zend_function *func) /* {{{ */
{
- zend_function *new_function;
-
- new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
- memcpy(new_function, func, sizeof(zend_op_array));
-
- if (CG(compiler_options) & ZEND_COMPILE_PRELOAD) {
- ZEND_ASSERT(new_function->op_array.fn_flags & ZEND_ACC_PRELOADED);
- ZEND_MAP_PTR_NEW(new_function->op_array.static_variables_ptr);
- } else {
- ZEND_MAP_PTR_INIT(new_function->op_array.static_variables_ptr, &new_function->op_array.static_variables);
- }
-
- HashTable *static_properties_ptr = ZEND_MAP_PTR_GET(func->op_array.static_variables_ptr);
- if (static_properties_ptr) {
- /* See: Zend/tests/method_static_var.phpt */
- ZEND_MAP_PTR_SET(new_function->op_array.static_variables_ptr, static_properties_ptr);
- GC_TRY_ADDREF(static_properties_ptr);
- } else {
- GC_TRY_ADDREF(new_function->op_array.static_variables);
- }
-
- return new_function;
+ zend_op_array *new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
+ memcpy(new_op_array, func, sizeof(zend_op_array));
+ zend_init_static_variables_map_ptr(new_op_array);
+ return (zend_function *) new_op_array;
}
/* }}} */
@@ -2504,12 +2486,17 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
for (; p != end; p++) {
zend_op_array *op_array, *new_op_array;
void ***run_time_cache_ptr;
+ size_t alloc_size;
op_array = Z_PTR(p->val);
ZEND_ASSERT(op_array->type == ZEND_USER_FUNCTION);
ZEND_ASSERT(op_array->scope == pce);
ZEND_ASSERT(op_array->prototype == NULL);
- new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array) + sizeof(void*));
+ alloc_size = sizeof(zend_op_array) + sizeof(void *);
+ if (op_array->static_variables) {
+ alloc_size += sizeof(HashTable *);
+ }
+ new_op_array = zend_arena_alloc(&CG(arena), alloc_size);
Z_PTR(p->val) = new_op_array;
memcpy(new_op_array, op_array, sizeof(zend_op_array));
run_time_cache_ptr = (void***)(new_op_array + 1);
@@ -2517,7 +2504,11 @@ static zend_class_entry *zend_lazy_class_load(zend_class_entry *pce)
new_op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
new_op_array->scope = ce;
ZEND_MAP_PTR_INIT(new_op_array->run_time_cache, run_time_cache_ptr);
- ZEND_MAP_PTR_INIT(new_op_array->static_variables_ptr, &new_op_array->static_variables);
+ if (op_array->static_variables) {
+ HashTable **static_variables_ptr = (HashTable **) (run_time_cache_ptr + 1);
+ *static_variables_ptr = NULL;
+ ZEND_MAP_PTR_INIT(new_op_array->static_variables_ptr, static_variables_ptr);
+ }
zend_update_inherited_handler(constructor);
zend_update_inherited_handler(destructor);