Skip to content

Commit a037a5b

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed second part of the bug #78379 (Cast to object confuses GC, causes crash)
2 parents 9b97355 + 1456467 commit a037a5b

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
@@ -699,11 +699,14 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
699699

700700
ht = obj->handlers->get_gc(obj, &zv, &n);
701701
end = zv + n;
702-
if (EXPECTED(!ht)) {
702+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
703+
ht = NULL;
703704
if (!n) goto next;
704705
while (!Z_REFCOUNTED_P(--end)) {
705706
if (zv == end) goto next;
706707
}
708+
} else {
709+
GC_REF_SET_BLACK(ht);
707710
}
708711
while (zv != end) {
709712
if (Z_REFCOUNTED_P(zv)) {
@@ -814,11 +817,14 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
814817

815818
ht = obj->handlers->get_gc(obj, &zv, &n);
816819
end = zv + n;
817-
if (EXPECTED(!ht)) {
820+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) {
821+
ht = NULL;
818822
if (!n) goto next;
819823
while (!Z_REFCOUNTED_P(--end)) {
820824
if (zv == end) goto next;
821825
}
826+
} else {
827+
GC_REF_SET_COLOR(ht, GC_GREY);
822828
}
823829
while (zv != end) {
824830
if (Z_REFCOUNTED_P(zv)) {
@@ -1000,11 +1006,14 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
10001006

10011007
ht = obj->handlers->get_gc(obj, &zv, &n);
10021008
end = zv + n;
1003-
if (EXPECTED(!ht)) {
1009+
if (EXPECTED(!ht) || UNEXPECTED(!GC_REF_CHECK_COLOR(ht, GC_GREY))) {
1010+
ht = NULL;
10041011
if (!n) goto next;
10051012
while (!Z_REFCOUNTED_P(--end)) {
10061013
if (zv == end) goto next;
10071014
}
1015+
} else {
1016+
GC_REF_SET_COLOR(ht, GC_WHITE);
10081017
}
10091018
while (zv != end) {
10101019
if (Z_REFCOUNTED_P(zv)) {
@@ -1167,7 +1176,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
11671176
}
11681177
ht = obj->handlers->get_gc(obj, &zv, &n);
11691178
end = zv + n;
1170-
if (EXPECTED(!ht)) {
1179+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
1180+
ht = NULL;
11711181
if (!n) goto next;
11721182
while (!Z_REFCOUNTED_P(--end)) {
11731183
/* count non-refcounted for compatibility ??? */
@@ -1176,6 +1186,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
11761186
}
11771187
if (zv == end) goto next;
11781188
}
1189+
} else {
1190+
GC_REF_SET_BLACK(ht);
11791191
}
11801192
while (zv != end) {
11811193
if (Z_REFCOUNTED_P(zv)) {

0 commit comments

Comments
 (0)