diff options
-rw-r--r-- | Zend/tests/assign_to_obj_001.phpt | 24 | ||||
-rw-r--r-- | Zend/zend_execute.c | 27 |
2 files changed, 40 insertions, 11 deletions
diff --git a/Zend/tests/assign_to_obj_001.phpt b/Zend/tests/assign_to_obj_001.phpt new file mode 100644 index 0000000000..4b3cd31b92 --- /dev/null +++ b/Zend/tests/assign_to_obj_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +assgin to object leaks with ref +--FILE-- +<?php +function &a($i) { + $a = "str". $i ."ing"; + return $a; +} + +class A { + public function test() { + $this->a = a(1); + unset($this->a); + } +} + +$a = new A; + +$a->test(); +$a->test(); +echo "okey"; +?> +--EXPECT-- +okey diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index cbe6ef1d80..eb37d48522 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1044,7 +1044,6 @@ fast_assign: } if (!zobj->ce->__set) { - zend_reference *ref = NULL; if (EXPECTED(zobj->properties == NULL)) { rebuild_object_properties(zobj); @@ -1059,11 +1058,22 @@ fast_assign: } else if (value_type != IS_TMP_VAR) { if (Z_ISREF_P(value)) { if (value_type == IS_VAR) { - ref = Z_REF_P(value); - } - value = Z_REFVAL_P(value); - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); + zend_reference *ref = Z_REF_P(value); + if (--(GC_REFCOUNT(ref)) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } } } else if (value_type == IS_CV && Z_REFCOUNTED_P(value)) { Z_ADDREF_P(value); @@ -1073,11 +1083,6 @@ fast_assign: if (retval) { ZVAL_COPY(retval, value); } - if (/*value_type == IS_VAR &&*/ ref) { - if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { - efree_size(ref, sizeof(zend_reference)); - } - } return; } } |