From: Dmitry Stogov Date: Thu, 1 Oct 2020 10:18:21 +0000 (+0300) Subject: Backport of a partial fix for bug Bug #76982 (memory leak declaring closure in includ... X-Git-Tag: php-7.3.24RC1~21 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=773f980e00af7ca45488d3c2879f5f6ba78c96e2;p=php Backport of a partial fix for bug Bug #76982 (memory leak declaring closure in included file). --- diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index b9d8bd1c75..022df9dabe 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -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; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6f9aca4b55..1b4eb5720d 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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) || diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e5e5a9e1da..be8b2b3a1f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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) ||