Skip to content
26 changes: 19 additions & 7 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -3956,19 +3956,21 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun
if (args_ast->kind == ZEND_AST_CALLABLE_CONVERT) {
opline = &CG(active_op_array)->opcodes[opnum_init];
opline->extended_value = 0;
/* opcode array may be reallocated, so don't access opcode field after zend_emit_op_tmp(). */
uint8_t opcode = opline->opcode;

if (opline->opcode == ZEND_NEW) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression");
if (opcode == ZEND_NEW) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot create Closure for new expression");
}

if (opline->opcode == ZEND_INIT_FCALL) {
if (opcode == ZEND_INIT_FCALL) {
opline->op1.num = zend_vm_calc_used_stack(0, fbc);
}

zend_op *callable_convert_op = zend_emit_op_tmp(result, ZEND_CALLABLE_CONVERT, NULL, NULL);
if (opline->opcode == ZEND_INIT_FCALL
|| opline->opcode == ZEND_INIT_FCALL_BY_NAME
|| opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
if (opcode == ZEND_INIT_FCALL
|| opcode == ZEND_INIT_FCALL_BY_NAME
|| opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
callable_convert_op->extended_value = zend_alloc_cache_slot();
} else {
callable_convert_op->extended_value = (uint32_t)-1;
Expand Down Expand Up @@ -8090,6 +8092,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;
Expand Down Expand Up @@ -8134,7 +8138,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++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ mysqli_fetch_all() data types variation
mysqli
--SKIPIF--
<?php
if (getenv('GITHUB_ACTIONS') && str_starts_with(php_uname('m'), 'ppc')) {
die('skip Flaky on GitHub Actions PPC runner');
}
require_once dirname(__DIR__) . "/test_setup/test_helpers.inc";
mysqli_check_skip_test();
?>
Expand Down
36 changes: 36 additions & 0 deletions ext/opcache/tests/gh19867.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
GH-19867: Avoid capturing nested arrow function parameters
--EXTENSIONS--
opcache
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.opt_debug_level=0x20000
--FILE--
<?php
fn() => 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
4 changes: 4 additions & 0 deletions ext/opcache/tests/gh19984.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ if (!function_exists('pcntl_fork')) die('skip pcntl_fork() not available');
<?php
$pid = pcntl_fork();
require __DIR__ . '/warning_replay.inc';
if ($pid) {
// Wait for child to output its error message.
pcntl_waitpid($pid, $status);
}
?>
--EXPECTF--
Warning: Unsupported declare 'unknown' in %s on line %d
Expand Down
6 changes: 6 additions & 0 deletions ext/standard/tests/general_functions/proc_open_multiplex.phpt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
--TEST--
Multiplexing of child output
--SKIPIF--
<?php
if (getenv('GITHUB_ACTIONS') && str_starts_with(php_uname('m'), 'ppc')) {
die('skip Flaky on GitHub Actions PPC runner');
}
?>
--FILE--
<?php
$php = getenv("TEST_PHP_EXECUTABLE");
Expand Down