Skip to content

Commit 32eed27

Browse files
committed
Disallow [] inside list()
1 parent 66faf11 commit 32eed27

File tree

3 files changed

+38
-50
lines changed

3 files changed

+38
-50
lines changed

Zend/tests/list_008.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Assignment to invalid list() value
3+
--FILE--
4+
<?php
5+
6+
[42] = [1];
7+
8+
?>
9+
--EXPECTF--
10+
Fatal error: Assignments can only happen to writable values in %s on line %d

Zend/zend_compile.c

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,13 +2559,13 @@ static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t
25592559

25602560
void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type);
25612561
void zend_compile_assign(znode *result, zend_ast *ast);
2562-
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node);
2562+
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node, zend_bool old_style);
25632563

25642564
static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
25652565
{
25662566
znode dummy_node;
25672567
if (var_ast->kind == ZEND_AST_ARRAY) {
2568-
zend_compile_list_assign(&dummy_node, var_ast, value_node);
2568+
zend_compile_list_assign(&dummy_node, var_ast, value_node, var_ast->attr);
25692569
} else {
25702570
zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
25712571
zend_ast_create_znode(value_node));
@@ -2709,14 +2709,18 @@ void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int d
27092709
}
27102710
/* }}} */
27112711

2712-
static void zend_verify_list_assign_target(zend_ast *var_ast) /* {{{ */ {
2713-
if (!zend_can_write_to_variable(var_ast) && var_ast->kind != ZEND_AST_ARRAY) {
2712+
static void zend_verify_list_assign_target(zend_ast *var_ast, zend_bool old_style) /* {{{ */ {
2713+
if (var_ast->kind == ZEND_AST_ARRAY) {
2714+
if (old_style != var_ast->attr) {
2715+
zend_error(E_COMPILE_ERROR, "Cannot mix [] and list()");
2716+
}
2717+
} else if (!zend_can_write_to_variable(var_ast)) {
27142718
zend_error(E_COMPILE_ERROR, "Assignments can only happen to writable values");
27152719
}
27162720
}
27172721
/* }}} */
27182722

2719-
static void zend_compile_unkeyed_list_assign(zend_ast_list *list, znode *expr_node) /* {{{ */
2723+
static void zend_compile_unkeyed_list_assign(zend_ast_list *list, znode *expr_node, zend_bool old_style) /* {{{ */
27202724
{
27212725
uint32_t i;
27222726
zend_bool has_elems = 0;
@@ -2744,7 +2748,7 @@ static void zend_compile_unkeyed_list_assign(zend_ast_list *list, znode *expr_no
27442748
zend_error(E_COMPILE_ERROR, "Cannot mix keyed and unkeyed array entries in assignments");
27452749
}
27462750

2747-
zend_verify_list_assign_target(var_ast);
2751+
zend_verify_list_assign_target(var_ast, old_style);
27482752

27492753
zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
27502754
zend_emit_assign_znode(var_ast, &fetch_result);
@@ -2756,7 +2760,7 @@ static void zend_compile_unkeyed_list_assign(zend_ast_list *list, znode *expr_no
27562760
}
27572761
/* }}} */
27582762

2759-
static void zend_compile_keyed_list_assign(zend_ast_list *list, znode *expr_node) /* {{{ */
2763+
static void zend_compile_keyed_list_assign(zend_ast_list *list, znode *expr_node, zend_bool old_style) /* {{{ */
27602764
{
27612765
uint32_t i;
27622766

@@ -2780,22 +2784,22 @@ static void zend_compile_keyed_list_assign(zend_ast_list *list, znode *expr_node
27802784
zend_error(E_COMPILE_ERROR, "Cannot mix keyed and unkeyed array entries in assignments");
27812785
}
27822786

2783-
zend_verify_list_assign_target(var_ast);
2787+
zend_verify_list_assign_target(var_ast, old_style);
27842788

27852789
zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
27862790
zend_emit_assign_znode(var_ast, &fetch_result);
27872791
}
27882792
}
27892793
/* }}} */
27902794

2791-
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
2795+
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node, zend_bool old_style) /* {{{ */
27922796
{
27932797
zend_ast_list *list = zend_ast_get_list(ast);
27942798

27952799
if (list->children > 0 && list->child[0] != NULL && list->child[0]->child[1] != NULL /* has key */) {
2796-
zend_compile_keyed_list_assign(list, expr_node);
2800+
zend_compile_keyed_list_assign(list, expr_node, old_style);
27972801
} else {
2798-
zend_compile_unkeyed_list_assign(list, expr_node);
2802+
zend_compile_unkeyed_list_assign(list, expr_node, old_style);
27992803
}
28002804

28012805
*result = *expr_node;
@@ -2944,7 +2948,7 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
29442948
zend_compile_expr(&expr_node, expr_ast);
29452949
}
29462950

2947-
zend_compile_list_assign(result, var_ast, &expr_node);
2951+
zend_compile_list_assign(result, var_ast, &expr_node, var_ast->attr);
29482952
return;
29492953
EMPTY_SWITCH_DEFAULT_CASE();
29502954
}
@@ -6347,6 +6351,10 @@ static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
63476351
uint32_t i;
63486352
zend_bool is_constant = 1;
63496353

6354+
if (ast->attr) {
6355+
zend_error(E_COMPILE_ERROR, "Cannot use list() as standalone expression");
6356+
}
6357+
63506358
/* First ensure that *all* child nodes are constant and by-val */
63516359
for (i = 0; i < list->children; ++i) {
63526360
zend_ast *elem_ast = list->child[i];

Zend/zend_language_parser.y

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
251251
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
252252
%type <ast> lexical_var_list encaps_list
253253
%type <ast> array_pair non_empty_array_pair_list array_pair_list
254-
%type <ast> assignment_pair non_empty_assignment_list assignment_list
255254
%type <ast> isset_variable type return_type
256255
%type <ast> identifier
257256

@@ -540,7 +539,7 @@ implements_list:
540539
foreach_variable:
541540
variable { $$ = $1; }
542541
| '&' variable { $$ = zend_ast_create(ZEND_AST_REF, $2); }
543-
| T_LIST '(' assignment_list ')' { $$ = $3; }
542+
| T_LIST '(' array_pair_list ')' { $3->attr = 1; $$ = $3; }
544543
| '[' array_pair_list ']' { $$ = $2; }
545544
;
546545

@@ -856,8 +855,8 @@ new_expr:
856855
;
857856

858857
expr_without_variable:
859-
T_LIST '(' assignment_list ')' '=' expr
860-
{ $$ = zend_ast_create(ZEND_AST_ASSIGN, $3, $6); }
858+
T_LIST '(' array_pair_list ')' '=' expr
859+
{ $3->attr = 1; $$ = zend_ast_create(ZEND_AST_ASSIGN, $3, $6); }
861860
| '[' array_pair_list ']' '=' expr
862861
{ $$ = zend_ast_create(ZEND_AST_ASSIGN, $2, $5); }
863862
| variable '=' expr
@@ -1169,39 +1168,6 @@ property_name:
11691168
| simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
11701169
;
11711170

1172-
assignment_list:
1173-
/* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_ARRAY); }
1174-
| non_empty_assignment_list { /* allow single trailing comma */ zend_ast_list *list = zend_ast_get_list($$ = $1); if (list->child[list->children - 1] == NULL) { list->children--; } }
1175-
;
1176-
1177-
non_empty_assignment_list:
1178-
non_empty_assignment_list ',' assignment_pair
1179-
{ $$ = zend_ast_list_add($1, $3); }
1180-
| assignment_pair
1181-
{ $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, $1); }
1182-
| non_empty_assignment_list ',' /* empty, for LHS array lists */
1183-
{ $$ = zend_ast_list_add($1, NULL); }
1184-
| ','
1185-
{ $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, NULL); }
1186-
| ',' assignment_pair
1187-
{ $$ = zend_ast_create_list(2, ZEND_AST_ARRAY, NULL, $2); }
1188-
;
1189-
1190-
assignment_pair:
1191-
expr T_DOUBLE_ARROW expr
1192-
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
1193-
| expr
1194-
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); }
1195-
| expr T_DOUBLE_ARROW '&' variable
1196-
{ $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); }
1197-
| '&' variable
1198-
{ $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); }
1199-
| expr T_DOUBLE_ARROW T_LIST '(' assignment_list ')'
1200-
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); }
1201-
| T_LIST '(' assignment_list ')'
1202-
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, NULL); }
1203-
;
1204-
12051171
array_pair_list:
12061172
/* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_ARRAY); }
12071173
| non_empty_array_pair_list { /* allow single trailing comma */ zend_ast_list *list = zend_ast_get_list($$ = $1); if (list->child[list->children - 1] == NULL) { list->children--; } }
@@ -1216,7 +1182,7 @@ non_empty_array_pair_list:
12161182
{ $$ = zend_ast_list_add($1, NULL); }
12171183
| ','
12181184
{ $$ = zend_ast_create_list(1, ZEND_AST_ARRAY, NULL); }
1219-
| ',' assignment_pair
1185+
| ',' array_pair
12201186
{ $$ = zend_ast_create_list(2, ZEND_AST_ARRAY, NULL, $2); }
12211187
;
12221188

@@ -1229,6 +1195,10 @@ array_pair:
12291195
{ $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $4, $1); }
12301196
| '&' variable
12311197
{ $$ = zend_ast_create_ex(ZEND_AST_ARRAY_ELEM, 1, $2, NULL); }
1198+
| expr T_DOUBLE_ARROW T_LIST '(' array_pair_list ')'
1199+
{ $5->attr = 1; $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); }
1200+
| T_LIST '(' array_pair_list ')'
1201+
{ $3->attr = 1; $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, NULL); }
12321202
;
12331203

12341204
encaps_list:

0 commit comments

Comments
 (0)