From ec12098c3b58e180334972e48c24d38f6ead66e2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 12 Apr 2006 11:38:09 +0000 Subject: [PATCH] Fixed bug #37046 (foreach breaks static scope) --- Zend/tests/bug37046.phpt | 23 +++++++++++++++ Zend/zend_vm_def.h | 15 +++++++++- Zend/zend_vm_execute.h | 64 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 95 insertions(+), 7 deletions(-) create mode 100755 Zend/tests/bug37046.phpt diff --git a/Zend/tests/bug37046.phpt b/Zend/tests/bug37046.phpt new file mode 100755 index 0000000000..8ade2a653c --- /dev/null +++ b/Zend/tests/bug37046.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #37046 (foreach breaks static scope) +--FILE-- + $function) { + echo "op1 $k\n"; + if ($k == 0) { + foreach (s() as $k => $function) { + echo "op2 $k\n"; + } + } +} +?> +--EXPEXT-- +op1 0 +op2 0 +op2 1 +op1 1 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index fcb3974a7f..808c0cb9d0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3096,7 +3096,20 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY) } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); } else { - array_ptr->refcount++; + if (OP1_TYPE == IS_VAR && + free_op1.var == NULL && + !array_ptr->is_ref && + array_ptr->refcount > 1) { + /* non-separated return value from function */ + zval *tmp; + + ALLOC_ZVAL(tmp); + INIT_PZVAL_COPY(tmp, array_ptr); + zval_copy_ctor(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c471927301..a08f576afe 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2030,7 +2030,7 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - + zend_free_op free_op1; zval *array_ptr, **array_ptr_ptr; HashTable *fe_ht; zend_object_iterator *iter = NULL; @@ -2071,7 +2071,20 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); } else { - array_ptr->refcount++; + if (IS_CONST == IS_VAR && + free_op1.var == NULL && + !array_ptr->is_ref && + array_ptr->refcount > 1) { + /* non-separated return value from function */ + zval *tmp; + + ALLOC_ZVAL(tmp); + INIT_PZVAL_COPY(tmp, array_ptr); + zval_copy_ctor(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } } } @@ -4554,7 +4567,20 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); } else { - array_ptr->refcount++; + if (IS_TMP_VAR == IS_VAR && + free_op1.var == NULL && + !array_ptr->is_ref && + array_ptr->refcount > 1) { + /* non-separated return value from function */ + zval *tmp; + + ALLOC_ZVAL(tmp); + INIT_PZVAL_COPY(tmp, array_ptr); + zval_copy_ctor(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } } } @@ -7634,7 +7660,20 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); } else { - array_ptr->refcount++; + if (IS_VAR == IS_VAR && + free_op1.var == NULL && + !array_ptr->is_ref && + array_ptr->refcount > 1) { + /* non-separated return value from function */ + zval *tmp; + + ALLOC_ZVAL(tmp); + INIT_PZVAL_COPY(tmp, array_ptr); + zval_copy_ctor(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } } } @@ -20213,7 +20252,7 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - + zend_free_op free_op1; zval *array_ptr, **array_ptr_ptr; HashTable *fe_ht; zend_object_iterator *iter = NULL; @@ -20254,7 +20293,20 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else if (Z_TYPE_P(array_ptr) == IS_OBJECT) { ce = Z_OBJCE_P(array_ptr); } else { - array_ptr->refcount++; + if (IS_CV == IS_VAR && + free_op1.var == NULL && + !array_ptr->is_ref && + array_ptr->refcount > 1) { + /* non-separated return value from function */ + zval *tmp; + + ALLOC_ZVAL(tmp); + INIT_PZVAL_COPY(tmp, array_ptr); + zval_copy_ctor(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } } } -- 2.40.0