Skip to content

Commit 22d23e0

Browse files
committed
Merge branch 'PHP-7.2' into PHP-7.3
* PHP-7.2: Fixed second part of the bug #78379 (Cast to object confuses GC, causes crash)
2 parents 21a0a28 + 6b1cc12 commit 22d23e0

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
@@ -701,11 +701,14 @@ static void gc_scan_black(zend_refcounted *ref, gc_stack *stack)
701701
ZVAL_OBJ(&tmp, obj);
702702
ht = get_gc(&tmp, &zv, &n);
703703
end = zv + n;
704-
if (EXPECTED(!ht)) {
704+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
705+
ht = NULL;
705706
if (!n) goto next;
706707
while (!Z_REFCOUNTED_P(--end)) {
707708
if (zv == end) goto next;
708709
}
710+
} else {
711+
GC_REF_SET_BLACK(ht);
709712
}
710713
while (zv != end) {
711714
if (Z_REFCOUNTED_P(zv)) {
@@ -820,11 +823,14 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
820823
ZVAL_OBJ(&tmp, obj);
821824
ht = get_gc(&tmp, &zv, &n);
822825
end = zv + n;
823-
if (EXPECTED(!ht)) {
826+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) {
827+
ht = NULL;
824828
if (!n) goto next;
825829
while (!Z_REFCOUNTED_P(--end)) {
826830
if (zv == end) goto next;
827831
}
832+
} else {
833+
GC_REF_SET_COLOR(ht, GC_GREY);
828834
}
829835
while (zv != end) {
830836
if (Z_REFCOUNTED_P(zv)) {
@@ -1010,11 +1016,14 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
10101016
ZVAL_OBJ(&tmp, obj);
10111017
ht = get_gc(&tmp, &zv, &n);
10121018
end = zv + n;
1013-
if (EXPECTED(!ht)) {
1019+
if (EXPECTED(!ht) || UNEXPECTED(!GC_REF_CHECK_COLOR(ht, GC_GREY))) {
1020+
ht = NULL;
10141021
if (!n) goto next;
10151022
while (!Z_REFCOUNTED_P(--end)) {
10161023
if (zv == end) goto next;
10171024
}
1025+
} else {
1026+
GC_REF_SET_COLOR(ht, GC_WHITE);
10181027
}
10191028
while (zv != end) {
10201029
if (Z_REFCOUNTED_P(zv)) {
@@ -1181,7 +1190,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
11811190
ZVAL_OBJ(&tmp, obj);
11821191
ht = get_gc(&tmp, &zv, &n);
11831192
end = zv + n;
1184-
if (EXPECTED(!ht)) {
1193+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
1194+
ht = NULL;
11851195
if (!n) goto next;
11861196
while (!Z_REFCOUNTED_P(--end)) {
11871197
/* count non-refcounted for compatibility ??? */
@@ -1190,6 +1200,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
11901200
}
11911201
if (zv == end) goto next;
11921202
}
1203+
} else {
1204+
GC_REF_SET_BLACK(ht);
11931205
}
11941206
while (zv != end) {
11951207
if (Z_REFCOUNTED_P(zv)) {

0 commit comments

Comments
 (0)