summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2007-12-28 13:22:00 +0000
committerDmitry Stogov <dmitry@php.net>2007-12-28 13:22:00 +0000
commit5a3eb537231a8d674ec57feeecb54f3188510061 (patch)
tree4b6a355e8f27b14cbb8b4cda18c07afc235e1ffd
parent2fa0078a71dd08b3dcde815485a3ecc40288595b (diff)
downloadphp-git-5a3eb537231a8d674ec57feeecb54f3188510061.tar.gz
Fixed bug #38469 (unexpected creation of cycle, json tests failed, leaks memory)
-rw-r--r--NEWS1
-rw-r--r--Zend/tests/bug38469.phpt28
-rw-r--r--Zend/zend_compile.c43
-rw-r--r--Zend/zend_language_parser.y2
4 files changed, 64 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index e68a144e82..598e3bd2b2 100644
--- a/NEWS
+++ b/NEWS
@@ -91,6 +91,7 @@ PHP NEWS
(Lars W)
- Fixed bug #39397 (invalid statement handle in Unknown on line 0). (Lars W)
- Fixed bug #39056 (Interbase NUMERIC data type error). (Lars W)
+- Fixed bug #38468 (Unexpected creation of cycle). (Dmitry)
- Fixed bug #37911 (preg_replace_callback() ignores named groups). (Nuno)
- Fixed bug #36128 (Interbase PDO - timestamp columns return NULL). (Lars W)
- Fixed bug #35386 (firebird: first row is null). (Lars W)
diff --git a/Zend/tests/bug38469.phpt b/Zend/tests/bug38469.phpt
new file mode 100644
index 0000000000..51fffb3008
--- /dev/null
+++ b/Zend/tests/bug38469.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #38469 Unexpected creation of cycle
+--FILE--
+<?php
+$a = array();
+$a[0] = $a;
+var_dump($a);
+$b = array(array());
+$b[0][0] = $b;
+var_dump($b);
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ array(0) {
+ }
+}
+array(1) {
+ [0]=>
+ array(1) {
+ [0]=>
+ array(1) {
+ [0]=>
+ array(0) {
+ }
+ }
+ }
+}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index e807df00fc..3ac034b07b 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -546,8 +546,39 @@ static zend_bool opline_is_fetch_this(zend_op *opline TSRMLS_DC)
void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ int last_op_number;
+ zend_op *opline;
+
+ if (value->op_type == IS_CV) {
+ zend_llist *fetch_list_ptr;
+
+ zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
+ if (fetch_list_ptr && fetch_list_ptr->head) {
+ opline = (zend_op *)fetch_list_ptr->head->data;
+
+ if (opline->opcode == ZEND_FETCH_DIM_W &&
+ opline->op1.op_type == IS_CV &&
+ opline->op1.u.var == value->u.var) {
+
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_FETCH_R;
+ opline->result.op_type = IS_VAR;
+ opline->result.u.EA.type = 0;
+ opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->op1.op_type = IS_CONST;
+ ZVAL_STRINGL(&opline->op1.u.constant,
+ CG(active_op_array)->vars[value->u.var].name,
+ CG(active_op_array)->vars[value->u.var].name_len, 1);
+ SET_UNUSED(opline->op2);
+ value = &opline->result;
+ }
+ }
+ }
+
+ zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+
+ last_op_number = get_next_op_number(CG(active_op_array));
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
if (variable->op_type == IS_VAR) {
int n = 0;
@@ -3840,8 +3871,6 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC)
zend_llist_element *dimension;
zend_op *opline;
znode last_container;
- int last_op_number;
- zend_op *last_op;
le = CG(list_llist).head;
while (le) {
@@ -3881,9 +3910,6 @@ void zend_do_list_end(znode *result, znode *expr TSRMLS_DC)
}
((list_llist_element *) le->data)->value = last_container;
zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
- last_op_number = get_next_op_number(CG(active_op_array))-1;
- last_op = &CG(active_op_array)->opcodes[last_op_number];
zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
zend_do_free(result TSRMLS_CC);
le = le->next;
@@ -4244,8 +4270,8 @@ void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znod
value_node = opline->result;
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
if (assign_by_ref) {
+ zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
} else {
@@ -4256,7 +4282,6 @@ void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znod
if (key->op_type != IS_UNUSED) {
znode key_node;
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
opline = &CG(active_op_array)->opcodes[as_token->u.opline_num+1];
opline->result.op_type = IS_TMP_VAR;
opline->result.u.EA.type = 0;
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index fe260c99d8..0f112974f7 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -560,7 +560,7 @@ non_empty_for_expr:
expr_without_variable:
T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
- | variable '=' expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
+ | variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
| variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
| variable '=' '&' T_NEW class_name_reference { zend_error(E_STRICT, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
| T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}