Skip to content

Commit 92e2f29

Browse files
committed
Fixed bug #63635 (Segfault in gc_collect_cycles)
1 parent bc49200 commit 92e2f29

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ PHP NEWS
33
?? ??? 2012, PHP 5.3.20
44

55
- Zend Engine:
6+
. Fixed bug #63635 (Segfault in gc_collect_cycles). (Dmitry)
67
. Fixed bug #63512 (parse_ini_file() with INI_SCANNER_RAW removes quotes
78
from value). (Pierrick)
89
. Fixed bug #63468 (wrong called method as callback with inheritance).

Zend/tests/bug63635.phpt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
Bug #63635 (Segfault in gc_collect_cycles)
3+
--FILE--
4+
<?php
5+
class Node {
6+
public $parent = NULL;
7+
public $childs = array();
8+
9+
function __construct(Node $parent=NULL) {
10+
if ($parent) {
11+
$parent->childs[] = $this;
12+
}
13+
$this->childs[] = $this;
14+
}
15+
16+
function __destruct() {
17+
$this->childs = NULL;
18+
}
19+
}
20+
21+
define("MAX", 16);
22+
23+
for ($n = 0; $n < 20; $n++) {
24+
$top = new Node();
25+
for ($i=0 ; $i<MAX ; $i++) {
26+
$ci = new Node($top);
27+
for ($j=0 ; $j<MAX ; $j++) {
28+
$cj = new Node($ci);
29+
for ($k=0 ; $k<MAX ; $k++) {
30+
$ck = new Node($cj);
31+
}
32+
}
33+
}
34+
echo "$n\n";
35+
}
36+
echo "ok\n";
37+
--EXPECT--
38+
0
39+
1
40+
2
41+
3
42+
4
43+
5
44+
6
45+
7
46+
8
47+
9
48+
10
49+
11
50+
12
51+
13
52+
14
53+
15
54+
16
55+
17
56+
18
57+
19
58+
ok

Zend/zend_gc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,8 @@ static void zval_collect_white(zval *pz TSRMLS_DC)
553553
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
554554

555555
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
556-
GC_SET_BLACK(obj->buffered);
556+
/* PURPLE instead of BLACK to prevent buffering in nested gc calls */
557+
GC_SET_PURPLE(obj->buffered);
557558

558559
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
559560
Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
@@ -598,7 +599,8 @@ static void zobj_collect_white(zval *pz TSRMLS_DC)
598599
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
599600

600601
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
601-
GC_SET_BLACK(obj->buffered);
602+
/* PURPLE instead of BLACK to prevent buffering in nested gc calls */
603+
GC_SET_PURPLE(obj->buffered);
602604

603605
if (EXPECTED(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].valid &&
604606
Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {

0 commit comments

Comments
 (0)