summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend-parser.y15
-rw-r--r--Zend/zend_compile.c6
-rw-r--r--Zend/zend_compile.h4
-rw-r--r--Zend/zend_execute.c46
4 files changed, 45 insertions, 26 deletions
diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y
index 58d39091fe..7081b4c3d4 100644
--- a/Zend/zend-parser.y
+++ b/Zend/zend-parser.y
@@ -602,18 +602,21 @@ assignment_list_element:
array_pair_list:
- /* empty */ { do_init_array(&$$, NULL, NULL CLS_CC); }
+ /* empty */ { do_init_array(&$$, NULL, NULL, 0 CLS_CC); }
| non_empty_array_pair_list { $$ = $1; }
;
non_empty_array_pair_list:
- non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { do_add_array_element(&$$, &$5, &$3 CLS_CC); }
- | non_empty_array_pair_list ',' expr { do_add_array_element(&$$, &$3, NULL CLS_CC); }
- | expr T_DOUBLE_ARROW expr { do_init_array(&$$, &$3, &$1 CLS_CC); }
- | expr { do_init_array(&$$, &$1, NULL CLS_CC); }
+ non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr { do_add_array_element(&$$, &$5, &$3, 0 CLS_CC); }
+ | non_empty_array_pair_list ',' expr { do_add_array_element(&$$, &$3, NULL, 0 CLS_CC); }
+ | expr T_DOUBLE_ARROW expr { do_init_array(&$$, &$3, &$1, 0 CLS_CC); }
+ | expr { do_init_array(&$$, &$1, NULL, 0 CLS_CC); }
+ | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_cvar { do_add_array_element(&$$, &$6, &$3, 1 CLS_CC); }
+ | non_empty_array_pair_list ',' '&' w_cvar { do_add_array_element(&$$, &$4, NULL, 1 CLS_CC); }
+ | expr T_DOUBLE_ARROW '&' w_cvar { do_init_array(&$$, &$4, &$1, 1 CLS_CC); }
+ | '&' w_cvar { do_init_array(&$$, &$2, NULL, 1 CLS_CC); }
;
-
encaps_list:
encaps_list encaps_var { do_end_variable_parse(BP_VAR_R, 0 CLS_CC); do_add_variable(&$$, &$1, &$2 CLS_CC); }
| encaps_list T_STRING { do_add_string(&$$, &$1, &$2 CLS_CC); }
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 16f2da3bf8..c85ccf983e 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1602,7 +1602,7 @@ void do_shell_exec(znode *result, znode *cmd CLS_DC)
-void do_init_array(znode *result, znode *expr, znode *offset CLS_DC)
+void do_init_array(znode *result, znode *expr, znode *offset, int is_ref CLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
@@ -1621,10 +1621,11 @@ void do_init_array(znode *result, znode *expr, znode *offset CLS_DC)
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
}
+ opline->extended_value = is_ref;
}
-void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC)
+void do_add_array_element(znode *result, znode *expr, znode *offset, int is_ref CLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) CLS_CC);
@@ -1636,6 +1637,7 @@ void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC)
} else {
SET_UNUSED(opline->op2);
}
+ opline->extended_value = is_ref;
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 5d368d2229..c1e886cbb1 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -304,8 +304,8 @@ void do_fetch_constant(znode *result, znode *constant_name, int mode CLS_DC);
void do_shell_exec(znode *result, znode *cmd CLS_DC);
-void do_init_array(znode *result, znode *expr, znode *offset CLS_DC);
-void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC);
+void do_init_array(znode *result, znode *expr, znode *offset, int is_ref CLS_DC);
+void do_add_array_element(znode *result, znode *expr, znode *offset, int is_ref CLS_DC);
void do_add_static_array_element(znode *result, znode *offset, znode *expr);
void do_list_init();
void do_list_end(znode *result, znode *expr CLS_DC);
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 604fdb0702..ece2f77404 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1804,43 +1804,57 @@ send_by_ref:
case ZEND_INIT_ARRAY:
case ZEND_ADD_ARRAY_ELEMENT: {
zval *array_ptr = &Ts[opline->result.u.var].tmp_var;
- zval *expr=get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
+ zval *expr_ptr, **expr_ptr_ptr;
zval *offset=get_zval_ptr(&opline->op2, Ts, &EG(free_op2), BP_VAR_R);
+ if (opline->extended_value) {
+ expr_ptr_ptr=get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R);
+ expr_ptr = *expr_ptr_ptr;
+ } else {
+ expr_ptr=get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
+ }
+
if (opline->opcode==ZEND_INIT_ARRAY) {
array_init(array_ptr);
- if (!expr) {
+ if (!expr_ptr) {
break;
}
}
- if (EG(free_op1)) { /* temporary variable */
+ if (opline->op1.op_type == IS_TMP_VAR) { /* temporary variable */
zval *new_expr = (zval *) emalloc(sizeof(zval));
- *new_expr = *expr;
- expr = new_expr;
- INIT_PZVAL(expr);
+ *new_expr = *expr_ptr;
+ expr_ptr = new_expr;
+ INIT_PZVAL(expr_ptr);
} else {
- if (PZVAL_IS_REF(expr)) {
+ if (opline->extended_value) {
+ if (!PZVAL_IS_REF(expr_ptr)) {
+ SEPARATE_ZVAL(expr_ptr_ptr);
+ expr_ptr = *expr_ptr_ptr;
+ expr_ptr->EA.is_ref = 1;
+ }
+ expr_ptr->refcount++;
+ } else if (PZVAL_IS_REF(expr_ptr)) {
zval *new_expr = (zval *) emalloc(sizeof(zval));
- *new_expr = *expr;
- expr = new_expr;
- zendi_zval_copy_ctor(*expr);
- INIT_PZVAL(expr);
+ *new_expr = *expr_ptr;
+ expr_ptr = new_expr;
+ zendi_zval_copy_ctor(*expr_ptr);
+ INIT_PZVAL(expr_ptr);
} else {
- expr->refcount++;
+ expr_ptr->refcount++;
}
}
if (offset) {
switch(offset->type) {
case IS_DOUBLE:
- zend_hash_index_update(array_ptr->value.ht, (long) offset->value.lval, &expr, sizeof(zval *), NULL);
+ zend_hash_index_update(array_ptr->value.ht, (long) offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_LONG:
- zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr, sizeof(zval *), NULL);
+ zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr, sizeof(zval *), NULL);
+ zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
break;
default:
/* do nothing */
@@ -1848,7 +1862,7 @@ send_by_ref:
}
FREE_OP(&opline->op2, EG(free_op2));
} else {
- zend_hash_next_index_insert(array_ptr->value.ht, &expr, sizeof(zval *), NULL);
+ zend_hash_next_index_insert(array_ptr->value.ht, &expr_ptr, sizeof(zval *), NULL);
}
}
break;