]> granicus.if.org Git - php/commitdiff
Fixed bug #39944 (References broken)
authorDmitry Stogov <dmitry@php.net>
Mon, 25 Dec 2006 14:16:38 +0000 (14:16 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 25 Dec 2006 14:16:38 +0000 (14:16 +0000)
Zend/tests/bug39944.phpt [new file with mode: 0755]
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug39944.phpt b/Zend/tests/bug39944.phpt
new file mode 100755 (executable)
index 0000000..4249988
--- /dev/null
@@ -0,0 +1,88 @@
+--TEST--
+Bug #39944 (References broken)
+--FILE--
+<?php
+$intTheValue = 0;
+
+function &getValue() {
+    global $intTheValue;
+    return $intTheValue;
+}
+
+function setValue(&$int, $iNewValue) {
+    $int = $iNewValue;
+}
+
+setValue(getValue(), 10);
+echo "intTheValue = {$intTheValue}\n";
+
+$b = &$intTheValue;
+
+setValue(getValue(), 10);
+echo "intTheValue = {$intTheValue}\n";
+
+/****/
+
+$arrTheArray = array();
+
+function &getArray() {
+       global $arrTheArray;
+       return $arrTheArray;
+}
+
+function addToArray(&$arr, $strToAdd) {
+       $arr[] = $strToAdd;
+}
+
+addToArray(getArray(), "xx1");
+$a = getArray();       
+addToArray($a, "xx2");
+$b = &$arrTheArray;
+addToArray($b, "xx3");
+addToArray(getArray(), "xx4");
+$a = getArray();       
+addToArray($a, "xx5");
+echo "arrTheArray = " . print_r($arrTheArray, 1);
+
+/****/
+
+class RefTest {
+       protected $arr;
+
+       function Add($strToAdd) {
+               $this->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
+)
index f21c242d04002ff48afa46811206873d517941a7..b8e8a36fca5503bf2b42a0c979890a228578d97b 100644 (file)
@@ -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))
index 30a3034de481d0d83387824b66fff6dd07c9db1e..86b5dc5471872259f42d75cbcc22603f25771b25 100644 (file)
@@ -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) &&
index fb986159692c44d9c83ab0e0ef660043d8478406..660f418ad9e07eb7f61eb4b01763b58dab520201 100644 (file)
@@ -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) &&