com php-src: Fixed bug #69446 (GC leak relating to removal of nested data after dtors run): Zend/tests/bug64896.phpt Zend/tests/bug69446.phpt
Zend/tests/bug69446_2.phpt Zend/zend_gc.c
| From: | Dmitry Stogov | Date: | Tue, 14 Apr 2015 16:53:56 +0000 |
| Subject: | com php-src: Fixed bug #69446 (GC leak relating to removal of nested data after dtors run): Zend/tests/bug64896.phpt Zend/tests/bug69446.phpt Zend/tests/bug69446_2.phpt Zend/zend_gc.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-86242@lists.php.net to get a copy of this message | ||
Commit: 00445ba22dd97988009692e2b35edaeff715f5e1
Author: Dmitry Stogov <dmitry@zend.com> Tue, 14 Apr 2015 19:53:56 +0300
Parents: 2256dbfb215f07f6147d011a0761dcca84a25f22
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=00445ba22dd97988009692e2b35edaeff715f5e1
Log:
Fixed bug #69446 (GC leak relating to removal of nested data after dtors run)
Bugs:
https://bugs.php.net/69446
Changed paths:
M Zend/tests/bug64896.phpt
A Zend/tests/bug69446.phpt
A Zend/tests/bug69446_2.phpt
M Zend/zend_gc.c
Diff:
diff --git a/Zend/tests/bug64896.phpt b/Zend/tests/bug64896.phpt
index f019697..3ff4a21 100644
--- a/Zend/tests/bug64896.phpt
+++ b/Zend/tests/bug64896.phpt
@@ -30,6 +30,7 @@ gc_disable();
unserialize(serialize($foo));
gc_collect_cycles();
var_dump($bar);
+gc_enable();
/* will output:
object(bad)#4 (1) {
["_private":"bad":private]=>
diff --git a/Zend/tests/bug69446.phpt b/Zend/tests/bug69446.phpt
new file mode 100644
index 0000000..b448a2b
--- /dev/null
+++ b/Zend/tests/bug69446.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #69446 (GC leak relating to removal of nested data after dtors run)
+--FILE--
+<?php
+$bar = NULL;
+class bad {
+ public function __destruct() {
+ global $bar;
+ $bar = $this;
+ $bar->y = new stdClass;
+ }
+}
+
+$foo = new stdClass;
+$foo->foo = $foo;
+$foo->bad = new bad;
+$foo->bad->x = new stdClass;
+
+unset($foo);
+gc_collect_cycles();
+var_dump($bar);
+--EXPECT--
+object(bad)#2 (2) {
+ ["x"]=>
+ object(stdClass)#3 (0) {
+ }
+ ["y"]=>
+ object(stdClass)#4 (0) {
+ }
+}
diff --git a/Zend/tests/bug69446_2.phpt b/Zend/tests/bug69446_2.phpt
new file mode 100644
index 0000000..520bd1f
--- /dev/null
+++ b/Zend/tests/bug69446_2.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Bug #69446 (GC leak relating to removal of nested data after dtors run)
+--FILE--
+<?php
+$bar = NULL;
+class bad
+{
+ public $_private = array();
+
+ public function __construct()
+ {
+ $this->_private[] = 'php';
+ }
+
+ public function __destruct()
+ {
+ global $bar;
+ $bar = $this;
+ }
+}
+
+$foo = new stdclass;
+$foo->foo = $foo;
+$foo->bad = new bad;
+
+unserialize(serialize($foo));
+//unset($foo);
+
+gc_collect_cycles();
+var_dump($bar);
+--EXPECT--
+object(bad)#4 (1) {
+ ["_private"]=>
+ array(1) {
+ [0]=>
+ string(3) "php"
+ }
+}
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 8669db1..d5c8ea8 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -720,7 +720,6 @@ static int gc_collect_roots(uint32_t *flags)
current = GC_G(roots).next;
while (current != &GC_G(roots)) {
if (GC_REF_GET_COLOR(current->ref) == GC_WHITE) {
- GC_REFCOUNT(current->ref)++;
count += gc_collect_white(current->ref, flags);
}
current = current->next;
@@ -832,7 +831,7 @@ static void gc_remove_nested_data_from_buffer(zend_refcounted *ref)
Bucket *p, *end;
tail_call:
- if (GC_ADDRESS(GC_INFO(ref)) != 0) {
+ if (GC_ADDRESS(GC_INFO(ref)) != 0 && GC_REF_GET_COLOR(ref) == GC_BLACK) {
GC_TRACE_REF(ref, "removing from buffer");
GC_REMOVE_FROM_BUFFER(ref);