Skip to content

Commit cede13c

Browse files
list() with keys (no foreach or tests)
1 parent 0e5fa32 commit cede13c

File tree

4 files changed

+105
-26
lines changed

4 files changed

+105
-26
lines changed

Zend/zend_compile.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2713,19 +2713,42 @@ static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_n
27132713
{
27142714
zend_ast_list *list = zend_ast_get_list(ast);
27152715
uint32_t i;
2716+
zend_ulong next_index = 0;
27162717
zend_bool has_elems = 0;
27172718

27182719
for (i = 0; i < list->children; ++i) {
2719-
zend_ast *var_ast = list->child[i];
2720+
zend_ast *pair_ast = list->child[i];
2721+
zend_ast *var_ast;
2722+
zend_ast *key_ast;
27202723
znode fetch_result, dim_node;
27212724

2722-
if (var_ast == NULL) {
2725+
if (pair_ast == NULL) {
2726+
next_index++;
27232727
continue;
27242728
}
2725-
has_elems = 1;
27262729

2727-
dim_node.op_type = IS_CONST;
2728-
ZVAL_LONG(&dim_node.u.constant, i);
2730+
var_ast = pair_ast->child[0];
2731+
key_ast = pair_ast->child[1];
2732+
2733+
if (key_ast) {
2734+
zend_compile_expr(&dim_node, key_ast);
2735+
zend_handle_numeric_op(&dim_node);
2736+
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);
2747+
2748+
next_index++;
2749+
}
2750+
2751+
has_elems = 1;
27292752

27302753
if (expr_node->op_type == IS_CONST) {
27312754
Z_TRY_ADDREF(expr_node->u.constant);

Zend/zend_language_parser.y

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,8 +1177,12 @@ assignment_list:
11771177
;
11781178

11791179
assignment_list_element:
1180-
variable { $$ = $1; }
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); }
11811183
| T_LIST '(' assignment_list ')' { $$ = $3; }
1184+
| scalar T_DOUBLE_ARROW T_LIST '(' assignment_list ')'
1185+
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); }
11821186
| /* empty */ { $$ = NULL; }
11831187
;
11841188

Zend/zend_vm_def.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,13 +2073,26 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMPVAR|CV, CONST)
20732073

20742074
ZEND_VM_C_LABEL(try_fetch_list):
20752075
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
2076-
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
2076+
zval *value;
2077+
2078+
if (Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_LONG) {
2079+
value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
20772080

2078-
if (UNEXPECTED(value == NULL)) {
2079-
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
2080-
ZVAL_NULL(EX_VAR(opline->result.var));
2081+
if (UNEXPECTED(value == NULL)) {
2082+
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
2083+
ZVAL_NULL(EX_VAR(opline->result.var));
2084+
} else {
2085+
ZVAL_COPY(EX_VAR(opline->result.var), value);
2086+
}
20812087
} else {
2082-
ZVAL_COPY(EX_VAR(opline->result.var), value);
2088+
value = zend_hash_find(Z_ARRVAL_P(container), Z_STR_P(EX_CONSTANT(opline->op2)));
2089+
2090+
if (UNEXPECTED(value == NULL)) {
2091+
zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
2092+
ZVAL_NULL(EX_VAR(opline->result.var));
2093+
} else {
2094+
ZVAL_COPY(EX_VAR(opline->result.var), value);
2095+
}
20832096
}
20842097
} else if (OP1_TYPE != IS_CONST &&
20852098
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&

Zend/zend_vm_execute.h

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5753,13 +5753,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CONST_CONST_HA
57535753

57545754
try_fetch_list:
57555755
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
5756-
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
5756+
zval *value;
57575757

5758-
if (UNEXPECTED(value == NULL)) {
5759-
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
5760-
ZVAL_NULL(EX_VAR(opline->result.var));
5758+
if (Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_LONG) {
5759+
value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
5760+
5761+
if (UNEXPECTED(value == NULL)) {
5762+
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
5763+
ZVAL_NULL(EX_VAR(opline->result.var));
5764+
} else {
5765+
ZVAL_COPY(EX_VAR(opline->result.var), value);
5766+
}
57615767
} else {
5762-
ZVAL_COPY(EX_VAR(opline->result.var), value);
5768+
value = zend_hash_find(Z_ARRVAL_P(container), Z_STR_P(EX_CONSTANT(opline->op2)));
5769+
5770+
if (UNEXPECTED(value == NULL)) {
5771+
zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
5772+
ZVAL_NULL(EX_VAR(opline->result.var));
5773+
} else {
5774+
ZVAL_COPY(EX_VAR(opline->result.var), value);
5775+
}
57635776
}
57645777
} else if (IS_CONST != IS_CONST &&
57655778
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
@@ -37866,13 +37879,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDL
3786637879

3786737880
try_fetch_list:
3786837881
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
37869-
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
37882+
zval *value;
3787037883

37871-
if (UNEXPECTED(value == NULL)) {
37872-
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
37873-
ZVAL_NULL(EX_VAR(opline->result.var));
37884+
if (Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_LONG) {
37885+
value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
37886+
37887+
if (UNEXPECTED(value == NULL)) {
37888+
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
37889+
ZVAL_NULL(EX_VAR(opline->result.var));
37890+
} else {
37891+
ZVAL_COPY(EX_VAR(opline->result.var), value);
37892+
}
3787437893
} else {
37875-
ZVAL_COPY(EX_VAR(opline->result.var), value);
37894+
value = zend_hash_find(Z_ARRVAL_P(container), Z_STR_P(EX_CONSTANT(opline->op2)));
37895+
37896+
if (UNEXPECTED(value == NULL)) {
37897+
zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
37898+
ZVAL_NULL(EX_VAR(opline->result.var));
37899+
} else {
37900+
ZVAL_COPY(EX_VAR(opline->result.var), value);
37901+
}
3787637902
}
3787737903
} else if (IS_CV != IS_CONST &&
3787837904
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
@@ -51017,13 +51043,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_H
5101751043

5101851044
try_fetch_list:
5101951045
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
51020-
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
51046+
zval *value;
5102151047

51022-
if (UNEXPECTED(value == NULL)) {
51023-
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
51024-
ZVAL_NULL(EX_VAR(opline->result.var));
51048+
if (Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_LONG) {
51049+
value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
51050+
51051+
if (UNEXPECTED(value == NULL)) {
51052+
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
51053+
ZVAL_NULL(EX_VAR(opline->result.var));
51054+
} else {
51055+
ZVAL_COPY(EX_VAR(opline->result.var), value);
51056+
}
5102551057
} else {
51026-
ZVAL_COPY(EX_VAR(opline->result.var), value);
51058+
value = zend_hash_find(Z_ARRVAL_P(container), Z_STR_P(EX_CONSTANT(opline->op2)));
51059+
51060+
if (UNEXPECTED(value == NULL)) {
51061+
zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
51062+
ZVAL_NULL(EX_VAR(opline->result.var));
51063+
} else {
51064+
ZVAL_COPY(EX_VAR(opline->result.var), value);
51065+
}
5102751066
}
5102851067
} else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
5102951068
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&

0 commit comments

Comments
 (0)