--- /dev/null
+--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
+)
#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;
/* 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;
}
}
}
}
-#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))
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) &&
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) &&
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) &&