]> granicus.if.org Git - php/commitdiff
Backport of a partial fix for bug Bug #76982 (memory leak declaring closure in includ...
authorDmitry Stogov <dmitry@zend.com>
Thu, 1 Oct 2020 10:18:21 +0000 (13:18 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 1 Oct 2020 10:18:21 +0000 (13:18 +0300)
Zend/zend_closures.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index b9d8bd1c75015bed8f9766a63430077534bfcaaf..022df9dabe52d8f1eac1a1a651967e4d9d846706 100644 (file)
@@ -666,6 +666,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
        if (func->type == ZEND_USER_FUNCTION) {
                memcpy(&closure->func, func, sizeof(zend_op_array));
                closure->func.common.fn_flags |= ZEND_ACC_CLOSURE;
+               closure->func.common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
                if (closure->func.op_array.static_variables) {
                        closure->func.op_array.static_variables =
                                zend_array_dup(closure->func.op_array.static_variables);
@@ -676,7 +677,9 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
                        || func->common.scope != scope
                        || (func->common.fn_flags & ZEND_ACC_NO_RT_ARENA)
                ) {
-                       if (!func->op_array.run_time_cache && (func->common.fn_flags & ZEND_ACC_CLOSURE)) {
+                       if (!func->op_array.run_time_cache
+                        && (func->common.fn_flags & ZEND_ACC_CLOSURE)
+                        && !(func->common.fn_flags & ZEND_ACC_IMMUTABLE)) {
                                /* If a real closure is used for the first time, we create a shared runtime cache
                                 * and remember which scope it is for. */
                                func->common.scope = scope;
index 6f9aca4b551669176c221ecdc77883581fd8bf82..1b4eb5720dd1cab2e1b3164d47210cefce03527e 100644 (file)
@@ -7097,15 +7097,6 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
        zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
        ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
 
-       fbc = Z_PTR_P(zfunc);
-       if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) {
-               zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
-
-               memcpy(new_func, fbc, sizeof(zend_op_array));
-               new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
-               Z_PTR_P(zfunc) = fbc = new_func;
-       }
-
        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                called_scope = Z_OBJCE(EX(This));
                if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||
index e5e5a9e1da89e5abc00acef367dab09e8d82c737..be8b2b3a1f2aaa65b3d38e5f8e6e2825824a6889 100644 (file)
@@ -9209,15 +9209,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_C
        zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
        ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
 
-       fbc = Z_PTR_P(zfunc);
-       if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) {
-               zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
-
-               memcpy(new_func, fbc, sizeof(zend_op_array));
-               new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
-               Z_PTR_P(zfunc) = fbc = new_func;
-       }
-
        if (Z_TYPE(EX(This)) == IS_OBJECT) {
                called_scope = Z_OBJCE(EX(This));
                if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||