]> granicus.if.org Git - php/commitdiff
Fixed mem leak in assign_to_obj with reference
authorXinchen Hui <laruence@php.net>
Tue, 21 Apr 2015 13:04:20 +0000 (21:04 +0800)
committerXinchen Hui <laruence@php.net>
Tue, 21 Apr 2015 13:04:20 +0000 (21:04 +0800)
Zend/tests/assign_to_obj_001.phpt [new file with mode: 0644]
Zend/zend_execute.c

diff --git a/Zend/tests/assign_to_obj_001.phpt b/Zend/tests/assign_to_obj_001.phpt
new file mode 100644 (file)
index 0000000..4b3cd31
--- /dev/null
@@ -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
index cbe6ef1d806635e37df6862b349f0e9f420abffb..eb37d48522b3d191c813d6ac9f7b5c379b1af0c8 100644 (file)
@@ -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;
                        }
        }