Skip to content

Commit 6b1cc12

Browse files
committed
Fixed second part of the bug #78379 (Cast to object confuses GC, causes crash)
1 parent 2e2cd65 commit 6b1cc12

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

Zend/tests/bug78379_2.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Bug #78379.2 (Cast to object confuses GC, causes crash)
3+
--FILE--
4+
<?php
5+
class E {}
6+
function f() {
7+
$e1 = new E;
8+
$e2 = new E;
9+
$a = ['e2' => $e2];
10+
$e1->a = (object)$a;
11+
$e2->e1 = $e1;
12+
$e2->a = (object)$a;
13+
}
14+
f();
15+
gc_collect_cycles();
16+
echo "End\n";
17+
?>
18+
--EXPECT--
19+
End

Zend/zend_gc.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -388,11 +388,14 @@ static void gc_scan_black(zend_refcounted *ref)
388388
ZVAL_OBJ(&tmp, obj);
389389
ht = get_gc(&tmp, &zv, &n);
390390
end = zv + n;
391-
if (EXPECTED(!ht)) {
391+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_BLACK)) {
392+
ht = NULL;
392393
if (!n) return;
393394
while (!Z_REFCOUNTED_P(--end)) {
394395
if (zv == end) return;
395396
}
397+
} else {
398+
GC_REF_SET_BLACK(ht);
396399
}
397400
while (zv != end) {
398401
if (Z_REFCOUNTED_P(zv)) {
@@ -498,11 +501,14 @@ static void gc_mark_grey(zend_refcounted *ref)
498501
ZVAL_OBJ(&tmp, obj);
499502
ht = get_gc(&tmp, &zv, &n);
500503
end = zv + n;
501-
if (EXPECTED(!ht)) {
504+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_GREY)) {
505+
ht = NULL;
502506
if (!n) return;
503507
while (!Z_REFCOUNTED_P(--end)) {
504508
if (zv == end) return;
505509
}
510+
} else {
511+
GC_REF_SET_COLOR(ht, GC_GREY);
506512
}
507513
while (zv != end) {
508514
if (Z_REFCOUNTED_P(zv)) {
@@ -616,11 +622,14 @@ static void gc_scan(zend_refcounted *ref)
616622
ZVAL_OBJ(&tmp, obj);
617623
ht = get_gc(&tmp, &zv, &n);
618624
end = zv + n;
619-
if (EXPECTED(!ht)) {
625+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) != GC_GREY)) {
626+
ht = NULL;
620627
if (!n) return;
621628
while (!Z_REFCOUNTED_P(--end)) {
622629
if (zv == end) return;
623630
}
631+
} else {
632+
GC_REF_SET_COLOR(ht, GC_WHITE);
624633
}
625634
while (zv != end) {
626635
if (Z_REFCOUNTED_P(zv)) {
@@ -791,7 +800,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags)
791800
ZVAL_OBJ(&tmp, obj);
792801
ht = get_gc(&tmp, &zv, &n);
793802
end = zv + n;
794-
if (EXPECTED(!ht)) {
803+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_BLACK)) {
804+
ht = NULL;
795805
if (!n) return count;
796806
while (!Z_REFCOUNTED_P(--end)) {
797807
/* count non-refcounted for compatibility ??? */
@@ -800,6 +810,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags)
800810
}
801811
if (zv == end) return count;
802812
}
813+
} else {
814+
GC_REF_SET_BLACK(ht);
803815
}
804816
while (zv != end) {
805817
if (Z_REFCOUNTED_P(zv)) {

0 commit comments

Comments
 (0)