summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/assign_to_obj_001.phpt24
-rw-r--r--Zend/zend_execute.c27
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;
}
}