summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2012-11-29 12:38:34 +0400
committerDmitry Stogov <dmitry@zend.com>2012-11-29 12:38:34 +0400
commitf877d7fee6efe6457e665e60f99fc2f524d26d52 (patch)
tree8726af8bd4b13a1a7b31ba98feb44b4e1571ed2a
parentc37d7a9456ff12fc60654a2b33aadedfcf6e7476 (diff)
parent92e2f2938115d2cdae185848d535380fb7694598 (diff)
downloadphp-git-f877d7fee6efe6457e665e60f99fc2f524d26d52.tar.gz
Merge branch 'PHP-5.3' into PHP-5.4
* PHP-5.3: Fixed bug #63635 (Segfault in gc_collect_cycles) Conflicts: NEWS
-rw-r--r--NEWS1
-rw-r--r--Zend/tests/bug63635.phpt58
-rw-r--r--Zend/zend_gc.c6
3 files changed, 63 insertions, 2 deletions
diff --git a/NEWS b/NEWS
index 79b4f286e5..20ef5e3bef 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PHP NEWS
?? ??? 2012, PHP 5.4.10
- Core:
+ . Fixed bug #63635 (Segfault in gc_collect_cycles). (Dmitry)
. Fixed bug #63468 (wrong called method as callback with inheritance).
(Laruence)
. Fixed bug #61272 (ob_start callback gets passed empty string).
diff --git a/Zend/tests/bug63635.phpt b/Zend/tests/bug63635.phpt
new file mode 100644
index 0000000000..6f6fc6a44f
--- /dev/null
+++ b/Zend/tests/bug63635.phpt
@@ -0,0 +1,58 @@
+--TEST--
+Bug #63635 (Segfault in gc_collect_cycles)
+--FILE--
+<?php
+class Node {
+ public $parent = NULL;
+ public $childs = array();
+
+ function __construct(Node $parent=NULL) {
+ if ($parent) {
+ $parent->childs[] = $this;
+ }
+ $this->childs[] = $this;
+ }
+
+ function __destruct() {
+ $this->childs = NULL;
+ }
+}
+
+define("MAX", 16);
+
+for ($n = 0; $n < 20; $n++) {
+ $top = new Node();
+ for ($i=0 ; $i<MAX ; $i++) {
+ $ci = new Node($top);
+ for ($j=0 ; $j<MAX ; $j++) {
+ $cj = new Node($ci);
+ for ($k=0 ; $k<MAX ; $k++) {
+ $ck = new Node($cj);
+ }
+ }
+ }
+ echo "$n\n";
+}
+echo "ok\n";
+--EXPECT--
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+ok
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index 84a99c169a..e877eab75d 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -644,7 +644,8 @@ tail_call:
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
- GC_SET_BLACK(obj->buffered);
+ /* PURPLE instead of BLACK to prevent buffering in nested gc calls */
+ GC_SET_PURPLE(obj->buffered);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
(get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {
@@ -715,7 +716,8 @@ static void zobj_collect_white(zval *pz TSRMLS_DC)
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
- GC_SET_BLACK(obj->buffered);
+ /* PURPLE instead of BLACK to prevent buffering in nested gc calls */
+ GC_SET_PURPLE(obj->buffered);
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
(get_gc = Z_OBJ_HANDLER_P(pz, get_gc)) != NULL)) {