diff options
| author | Dmitry Stogov <dmitry@php.net> | 2007-12-28 13:38:20 +0000 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@php.net> | 2007-12-28 13:38:20 +0000 |
| commit | 2705adc4b9a79204a6de3ae28c0b4ca01ed13e31 (patch) | |
| tree | cceda01699eb210b3bcd6102745d89c2e12cf85c /Zend | |
| parent | 97c1cc892538fec0e17410acb805e13be38b13cd (diff) | |
| download | php-git-2705adc4b9a79204a6de3ae28c0b4ca01ed13e31.tar.gz | |
Fixed bug #38469 (Unexpected creation of cycle).
Diffstat (limited to 'Zend')
| -rw-r--r-- | Zend/tests/bug38469.phpt | 28 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 43 | ||||
| -rw-r--r-- | Zend/zend_language_parser.y | 2 |
3 files changed, 63 insertions, 10 deletions
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 0a7c5a338d..f7083442da 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -541,8 +541,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; @@ -3420,8 +3451,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) { @@ -3461,9 +3490,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; @@ -3824,9 +3850,9 @@ 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) { /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ + zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); } else { zend_do_assign(&dummy, value, &value_node TSRMLS_CC); @@ -3836,7 +3862,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 017c96dc4e..1fe6759e26 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -551,7 +551,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, 0 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);} |
