Skip to content

Commit e572d2d

Browse files
Disallow mixing keyed and unkeyed list() elements
1 parent cede13c commit e572d2d

File tree

2 files changed

+71
-37
lines changed

2 files changed

+71
-37
lines changed

Zend/zend_compile.c

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2709,46 +2709,53 @@ void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int d
27092709
}
27102710
/* }}} */
27112711

2712-
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
2712+
static void zend_compile_unkeyed_list_assign(zend_ast_list *list, znode *expr_node) /* {{{ */
27132713
{
2714-
zend_ast_list *list = zend_ast_get_list(ast);
27152714
uint32_t i;
2716-
zend_ulong next_index = 0;
27172715
zend_bool has_elems = 0;
27182716

27192717
for (i = 0; i < list->children; ++i) {
2720-
zend_ast *pair_ast = list->child[i];
2721-
zend_ast *var_ast;
2722-
zend_ast *key_ast;
2718+
zend_ast *var_ast = list->child[i];
27232719
znode fetch_result, dim_node;
27242720

2725-
if (pair_ast == NULL) {
2726-
next_index++;
2721+
if (var_ast == NULL) {
27272722
continue;
27282723
}
2724+
has_elems = 1;
27292725

2730-
var_ast = pair_ast->child[0];
2731-
key_ast = pair_ast->child[1];
2726+
dim_node.op_type = IS_CONST;
2727+
ZVAL_LONG(&dim_node.u.constant, i);
27322728

2733-
if (key_ast) {
2734-
zend_compile_expr(&dim_node, key_ast);
2735-
zend_handle_numeric_op(&dim_node);
2729+
if (expr_node->op_type == IS_CONST) {
2730+
Z_TRY_ADDREF(expr_node->u.constant);
2731+
}
27362732

2737-
if (Z_TYPE(dim_node.u.constant) != IS_LONG && Z_TYPE(dim_node.u.constant) != IS_STRING) {
2738-
zend_error_noreturn(E_COMPILE_ERROR, "Key must be an integer or string literal");
2739-
}
2740-
2741-
if (Z_TYPE(dim_node.u.constant) == IS_LONG) {
2742-
next_index = Z_LVAL(dim_node.u.constant);
2743-
}
2744-
} else {
2745-
dim_node.op_type = IS_CONST;
2746-
ZVAL_LONG(&dim_node.u.constant, next_index);
2733+
zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
2734+
zend_emit_assign_znode(var_ast, &fetch_result);
2735+
}
27472736

2748-
next_index++;
2749-
}
2737+
if (!has_elems) {
2738+
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
2739+
}
2740+
}
2741+
/* }}} */
27502742

2751-
has_elems = 1;
2743+
static void zend_compile_keyed_list_assign(zend_ast_list *list, znode *expr_node) /* {{{ */
2744+
{
2745+
uint32_t i;
2746+
2747+
for (i = 0; i < list->children; ++i) {
2748+
zend_ast *pair_ast = list->child[i];
2749+
zend_ast *var_ast = pair_ast->child[0];
2750+
zend_ast *key_ast = pair_ast->child[1];
2751+
znode fetch_result, dim_node;
2752+
2753+
zend_compile_expr(&dim_node, key_ast);
2754+
zend_handle_numeric_op(&dim_node);
2755+
2756+
if (Z_TYPE(dim_node.u.constant) != IS_LONG && Z_TYPE(dim_node.u.constant) != IS_STRING) {
2757+
zend_error_noreturn(E_COMPILE_ERROR, "Key must be an integer or string literal");
2758+
}
27522759

27532760
if (expr_node->op_type == IS_CONST) {
27542761
Z_TRY_ADDREF(expr_node->u.constant);
@@ -2757,9 +2764,17 @@ static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_n
27572764
zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
27582765
zend_emit_assign_znode(var_ast, &fetch_result);
27592766
}
2767+
}
2768+
/* }}} */
27602769

2761-
if (!has_elems) {
2762-
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
2770+
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
2771+
{
2772+
zend_ast_list *list = zend_ast_get_list(ast);
2773+
2774+
if (list->children > 0 && list->child[0] != NULL && list->child[0]->kind == ZEND_AST_ARRAY_ELEM) {
2775+
zend_compile_keyed_list_assign(list, expr_node);
2776+
} else {
2777+
zend_compile_unkeyed_list_assign(list, expr_node);
27632778
}
27642779

27652780
*result = *expr_node;

Zend/zend_language_parser.y

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
241241
%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name
242242
%type <ast> variable_class_name dereferencable_scalar constant dereferencable
243243
%type <ast> callable_expr callable_variable static_member new_variable
244-
%type <ast> assignment_list_element array_pair encaps_var encaps_var_offset isset_variables
244+
%type <ast> unkeyed_assignment_list_element keyed_assignment_list_element array_pair
245+
%type <ast> encaps_var encaps_var_offset isset_variables
245246
%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
246247
%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list
247248
%type <ast> echo_expr_list unset_variables catch_list parameter_list class_statement_list
@@ -250,7 +251,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
250251
%type <ast> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs
251252
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
252253
%type <ast> lexical_var_list encaps_list array_pair_list non_empty_array_pair_list
253-
%type <ast> assignment_list isset_variable type return_type
254+
%type <ast> assignment_list unkeyed_assignment_list keyed_assignment_list
255+
%type <ast> isset_variable type return_type
254256
%type <ast> identifier
255257

256258
%type <num> returns_ref function is_reference is_variadic variable_modifiers
@@ -1170,20 +1172,37 @@ property_name:
11701172
;
11711173

11721174
assignment_list:
1173-
assignment_list ',' assignment_list_element
1175+
unkeyed_assignment_list
1176+
{ $$ = $1; }
1177+
| keyed_assignment_list
1178+
{ $$ = $1; }
1179+
;
1180+
1181+
unkeyed_assignment_list:
1182+
unkeyed_assignment_list ',' unkeyed_assignment_list_element
11741183
{ $$ = zend_ast_list_add($1, $3); }
1175-
| assignment_list_element
1184+
| unkeyed_assignment_list_element
11761185
{ $$ = zend_ast_create_list(1, ZEND_AST_LIST, $1); }
11771186
;
11781187

1179-
assignment_list_element:
1180-
variable { $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $1, NULL); }
1181-
| scalar T_DOUBLE_ARROW variable
1182-
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
1188+
unkeyed_assignment_list_element:
1189+
variable { $$ = $1; }
11831190
| T_LIST '(' assignment_list ')' { $$ = $3; }
1191+
| /* empty */ { $$ = NULL; }
1192+
;
1193+
1194+
keyed_assignment_list:
1195+
keyed_assignment_list ',' keyed_assignment_list_element
1196+
{ $$ = zend_ast_list_add($1, $3); }
1197+
| keyed_assignment_list_element
1198+
{ $$ = zend_ast_create_list(1, ZEND_AST_LIST, $1); }
1199+
;
1200+
1201+
keyed_assignment_list_element:
1202+
scalar T_DOUBLE_ARROW variable
1203+
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
11841204
| scalar T_DOUBLE_ARROW T_LIST '(' assignment_list ')'
11851205
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); }
1186-
| /* empty */ { $$ = NULL; }
11871206
;
11881207

11891208

0 commit comments

Comments
 (0)