mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Fix self-assign evaluation order for ASSIGN_DIM_OP
For $ary[idx] op= $ary we should evaluate the RHS operand first, otherwise we may create a reference-free recursive array. Use the same handling we do for the normal $ary[idx] = $ary case. Fixes oss-fuzz #40287.
This commit is contained in:
parent
a4ed17167c
commit
55aadc647b
19
Zend/tests/assign_dim_op_same_var.phpt
Normal file
19
Zend/tests/assign_dim_op_same_var.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Compound array assignment with same variable
|
||||
--FILE--
|
||||
<?php
|
||||
function test() {
|
||||
$ary = [[]];
|
||||
$ary[0] += $ary;
|
||||
foreach ($ary as $v) {
|
||||
var_dump($v);
|
||||
}
|
||||
}
|
||||
test();
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
@ -3152,6 +3152,22 @@ static bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_compile_expr_with_potential_assign_to_self(
|
||||
znode *expr_node, zend_ast *expr_ast, zend_ast *var_ast) {
|
||||
if (zend_is_assign_to_self(var_ast, expr_ast) && !is_this_fetch(expr_ast)) {
|
||||
/* $a[0] = $a should evaluate the right $a first */
|
||||
znode cv_node;
|
||||
|
||||
if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) {
|
||||
zend_compile_simple_var_no_cv(expr_node, expr_ast, BP_VAR_R, 0);
|
||||
} else {
|
||||
zend_emit_op_tmp(expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
|
||||
}
|
||||
} else {
|
||||
zend_compile_expr(expr_node, expr_ast);
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
{
|
||||
zend_ast *var_ast = ast->child[0];
|
||||
@ -3192,20 +3208,7 @@ static void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
case ZEND_AST_DIM:
|
||||
offset = zend_delayed_compile_begin();
|
||||
zend_delayed_compile_dim(result, var_ast, BP_VAR_W);
|
||||
|
||||
if (zend_is_assign_to_self(var_ast, expr_ast)
|
||||
&& !is_this_fetch(expr_ast)) {
|
||||
/* $a[0] = $a should evaluate the right $a first */
|
||||
znode cv_node;
|
||||
|
||||
if (zend_try_compile_cv(&cv_node, expr_ast) == FAILURE) {
|
||||
zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
|
||||
} else {
|
||||
zend_emit_op_tmp(&expr_node, ZEND_QM_ASSIGN, &cv_node, NULL);
|
||||
}
|
||||
} else {
|
||||
zend_compile_expr(&expr_node, expr_ast);
|
||||
}
|
||||
zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
|
||||
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
opline->opcode = ZEND_ASSIGN_DIM;
|
||||
@ -3375,7 +3378,7 @@ static void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
case ZEND_AST_DIM:
|
||||
offset = zend_delayed_compile_begin();
|
||||
zend_delayed_compile_dim(result, var_ast, BP_VAR_RW);
|
||||
zend_compile_expr(&expr_node, expr_ast);
|
||||
zend_compile_expr_with_potential_assign_to_self(&expr_node, expr_ast, var_ast);
|
||||
|
||||
opline = zend_delayed_compile_end(offset);
|
||||
opline->opcode = ZEND_ASSIGN_DIM_OP;
|
||||
@ -8962,17 +8965,8 @@ static void zend_compile_assign_coalesce(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_emit_op_tmp(result, ZEND_COALESCE, &var_node_is, NULL);
|
||||
|
||||
CG(memoize_mode) = ZEND_MEMOIZE_NONE;
|
||||
if (var_ast->kind == ZEND_AST_DIM
|
||||
&& zend_is_assign_to_self(var_ast, default_ast)
|
||||
&& !is_this_fetch(default_ast)) {
|
||||
/* $a[0] = $a should evaluate the right $a first */
|
||||
znode cv_node;
|
||||
|
||||
if (zend_try_compile_cv(&cv_node, default_ast) == FAILURE) {
|
||||
zend_compile_simple_var_no_cv(&default_node, default_ast, BP_VAR_R, 0);
|
||||
} else {
|
||||
zend_emit_op_tmp(&default_node, ZEND_QM_ASSIGN, &cv_node, NULL);
|
||||
}
|
||||
if (var_ast->kind == ZEND_AST_DIM) {
|
||||
zend_compile_expr_with_potential_assign_to_self(&default_node, default_ast, var_ast);
|
||||
} else {
|
||||
zend_compile_expr(&default_node, default_ast);
|
||||
}
|
||||
|
@ -11,10 +11,8 @@ $a = null;
|
||||
$a[] .= $a;
|
||||
var_dump($a);
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: Array to string conversion in %sassign_dim_op_004.php on line 3
|
||||
--EXPECT--
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(5) "Array"
|
||||
string(0) ""
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user