diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 57c012ac71a6..a54cce0f5579 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8083,6 +8083,8 @@ typedef struct { bool varvars_used; } closure_info; +static void find_implicit_binds(closure_info *info, zend_ast *params_ast, zend_ast *stmt_ast); + static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) { if (!ast) { return; @@ -8127,7 +8129,15 @@ static void find_implicit_binds_recursively(closure_info *info, zend_ast *ast) { } else if (ast->kind == ZEND_AST_ARROW_FUNC) { /* For arrow functions recursively check the expression. */ zend_ast_decl *closure_ast = (zend_ast_decl *) ast; - find_implicit_binds_recursively(info, closure_ast->child[2]); + closure_info inner_info; + find_implicit_binds(&inner_info, closure_ast->child[0], closure_ast->child[2]); + if (inner_info.varvars_used) { + info->varvars_used = true; + } + if (zend_hash_num_elements(&inner_info.uses)) { + zend_hash_copy(&info->uses, &inner_info.uses, NULL); + } + zend_hash_destroy(&inner_info.uses); } else if (!zend_ast_is_special(ast)) { uint32_t i, children = zend_ast_get_num_children(ast); for (i = 0; i < children; i++) { diff --git a/ext/opcache/tests/gh19867.phpt b/ext/opcache/tests/gh19867.phpt new file mode 100644 index 000000000000..bbe957b20886 --- /dev/null +++ b/ext/opcache/tests/gh19867.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-19867: Avoid capturing nested arrow function parameters +--EXTENSIONS-- +opcache +--INI-- +opcache.enable_cli=1 +opcache.opt_debug_level=0x20000 +--FILE-- + fn($a, $b) => $a + $b; +?> +--EXPECTF-- +$_main: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0001 FREE T0 +0002 RETURN int(1) + +{closure:%s:%d}: + ; (lines=%d, args=0, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 T0 = DECLARE_LAMBDA_FUNCTION 0 +0001 RETURN T0 + +{closure:%s:%d}: + ; (lines=%d, args=2, vars=%d, tmps=%d) + ; (after optimizer) + ; %s +0000 CV0($a) = RECV 1 +0001 CV1($b) = RECV 2 +0002 T2 = ADD CV0($a) CV1($b) +0003 RETURN T2