From 326fcd0261baae9afb49ddd5ce4a46ad58232ccb Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Dec 2006 14:16:38 +0000 Subject: [PATCH] Fixed bug #39944 (References broken) --- Zend/tests/bug39944.phpt | 88 ++++++++++++++++++++++++++++++++++++++++ Zend/zend_execute.c | 7 ++-- Zend/zend_vm_def.h | 10 ++++- Zend/zend_vm_execute.h | 20 ++++++++- 4 files changed, 119 insertions(+), 6 deletions(-) create mode 100755 Zend/tests/bug39944.phpt diff --git a/Zend/tests/bug39944.phpt b/Zend/tests/bug39944.phpt new file mode 100755 index 0000000000..4249988ffd --- /dev/null +++ b/Zend/tests/bug39944.phpt @@ -0,0 +1,88 @@ +--TEST-- +Bug #39944 (References broken) +--FILE-- +addToArray($this->getArray(), $strToAdd); + } + + function &getArray() { + if (!$this->arr) + $this->arr = array(); + return $this->arr; + } + + private function addToArray(&$arr, $strToAdd) { + $arr[] = $strToAdd; + } +} + +$objRefTest = new RefTest(); +$objRefTest->Add("xx1"); +$objRefTest->Add("xx2"); +$objRefTest->Add("xx3"); + +echo "objRefTest->getArray() = " . print_r($objRefTest->getArray(), 1); +?> +--EXPECT-- +intTheValue = 10 +intTheValue = 10 +arrTheArray = Array +( + [0] => xx1 + [1] => xx3 + [2] => xx4 +) +objRefTest->getArray() = Array +( + [0] => xx1 + [1] => xx2 + [2] => xx3 +) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index f21c242d04..b8e8a36fca 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -65,7 +65,7 @@ static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_ #define TEMP_VAR_STACK_LIMIT 2000 -static inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free) +static inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref) { if (!--z->refcount) { z->refcount = 1; @@ -74,7 +74,7 @@ static inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free) /* should_free->is_var = 1; */ } else { should_free->var = 0; - if (z->is_ref && z->refcount == 1) { + if (unref && z->is_ref && z->refcount == 1) { z->is_ref = 0; } } @@ -88,7 +88,8 @@ static inline void zend_pzval_unlock_free_func(zval *z) } } -#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f) +#define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1) +#define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u) #define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z) #define PZVAL_LOCK(z) (z)->refcount++ #define RETURN_VALUE_UNUSED(pzn) (((pzn)->u.EA.type & EXT_TYPE_UNUSED)) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 30a3034de4..86b5dc5471 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2266,7 +2266,15 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY) ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper); } - varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); + if (OP1_TYPE == IS_VAR && + (opline->extended_value & ZEND_ARG_SEND_FUNCTION) && + EX_T(opline->op1.u.var).var.fcall_returned_reference && + EX_T(opline->op1.u.var).var.ptr) { + varptr = EX_T(opline->op1.u.var).var.ptr; + PZVAL_UNLOCK_EX(varptr, &free_op1, 0); + } else { + varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); + } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.u.var).var.fcall_returned_reference) && varptr != &EG(uninitialized_zval) && diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fb98615969..660f418ad9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7513,7 +7513,15 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + if (IS_VAR == IS_VAR && + (opline->extended_value & ZEND_ARG_SEND_FUNCTION) && + EX_T(opline->op1.u.var).var.fcall_returned_reference && + EX_T(opline->op1.u.var).var.ptr) { + varptr = EX_T(opline->op1.u.var).var.ptr; + PZVAL_UNLOCK_EX(varptr, &free_op1, 0); + } else { + varptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.u.var).var.fcall_returned_reference) && varptr != &EG(uninitialized_zval) && @@ -20068,7 +20076,15 @@ static int ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - varptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + if (IS_CV == IS_VAR && + (opline->extended_value & ZEND_ARG_SEND_FUNCTION) && + EX_T(opline->op1.u.var).var.fcall_returned_reference && + EX_T(opline->op1.u.var).var.ptr) { + varptr = EX_T(opline->op1.u.var).var.ptr; + PZVAL_UNLOCK_EX(varptr, &free_op1, 0); + } else { + varptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.u.var).var.fcall_returned_reference) && varptr != &EG(uninitialized_zval) && -- 2.40.0