diff options
author | Dmitry Stogov <dmitry@zend.com> | 2012-11-29 12:38:34 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2012-11-29 12:38:34 +0400 |
commit | f877d7fee6efe6457e665e60f99fc2f524d26d52 (patch) | |
tree | 8726af8bd4b13a1a7b31ba98feb44b4e1571ed2a | |
parent | c37d7a9456ff12fc60654a2b33aadedfcf6e7476 (diff) | |
parent | 92e2f2938115d2cdae185848d535380fb7694598 (diff) | |
download | php-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-- | NEWS | 1 | ||||
-rw-r--r-- | Zend/tests/bug63635.phpt | 58 | ||||
-rw-r--r-- | Zend/zend_gc.c | 6 |
3 files changed, 63 insertions, 2 deletions
@@ -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)) { |