Skip to content

Commit 1456467

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

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 = obj->handlers->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)) {
@@ -818,11 +821,14 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack)
818821
ZVAL_OBJ(&tmp, obj);
819822
ht = obj->handlers->get_gc(&tmp, &zv, &n);
820823
end = zv + n;
821-
if (EXPECTED(!ht)) {
824+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) {
825+
ht = NULL;
822826
if (!n) goto next;
823827
while (!Z_REFCOUNTED_P(--end)) {
824828
if (zv == end) goto next;
825829
}
830+
} else {
831+
GC_REF_SET_COLOR(ht, GC_GREY);
826832
}
827833
while (zv != end) {
828834
if (Z_REFCOUNTED_P(zv)) {
@@ -1006,11 +1012,14 @@ static void gc_scan(zend_refcounted *ref, gc_stack *stack)
10061012
ZVAL_OBJ(&tmp, obj);
10071013
ht = obj->handlers->get_gc(&tmp, &zv, &n);
10081014
end = zv + n;
1009-
if (EXPECTED(!ht)) {
1015+
if (EXPECTED(!ht) || UNEXPECTED(!GC_REF_CHECK_COLOR(ht, GC_GREY))) {
1016+
ht = NULL;
10101017
if (!n) goto next;
10111018
while (!Z_REFCOUNTED_P(--end)) {
10121019
if (zv == end) goto next;
10131020
}
1021+
} else {
1022+
GC_REF_SET_COLOR(ht, GC_WHITE);
10141023
}
10151024
while (zv != end) {
10161025
if (Z_REFCOUNTED_P(zv)) {
@@ -1175,7 +1184,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
11751184
ZVAL_OBJ(&tmp, obj);
11761185
ht = obj->handlers->get_gc(&tmp, &zv, &n);
11771186
end = zv + n;
1178-
if (EXPECTED(!ht)) {
1187+
if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) {
1188+
ht = NULL;
11791189
if (!n) goto next;
11801190
while (!Z_REFCOUNTED_P(--end)) {
11811191
/* count non-refcounted for compatibility ??? */
@@ -1184,6 +1194,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta
11841194
}
11851195
if (zv == end) goto next;
11861196
}
1197+
} else {
1198+
GC_REF_SET_BLACK(ht);
11871199
}
11881200
while (zv != end) {
11891201
if (Z_REFCOUNTED_P(zv)) {

0 commit comments

Comments
 (0)