Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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