From: Dmitry Stogov Date: Fri, 9 Aug 2019 12:42:39 +0000 (+0300) Subject: Fixed second part of the bug #78379 (Cast to object confuses GC, causes crash) X-Git-Tag: php-7.3.9RC1~7^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b1cc1252e73e51e53194c8c65e3d2302bc83dca;p=php Fixed second part of the bug #78379 (Cast to object confuses GC, causes crash) --- diff --git a/Zend/tests/bug78379_2.phpt b/Zend/tests/bug78379_2.phpt new file mode 100644 index 0000000000..0a515a2b07 --- /dev/null +++ b/Zend/tests/bug78379_2.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #78379.2 (Cast to object confuses GC, causes crash) +--FILE-- + $e2]; + $e1->a = (object)$a; + $e2->e1 = $e1; + $e2->a = (object)$a; +} +f(); +gc_collect_cycles(); +echo "End\n"; +?> +--EXPECT-- +End diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index 30ca4d0a2a..55f7271e3f 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -388,11 +388,14 @@ tail_call: ZVAL_OBJ(&tmp, obj); ht = get_gc(&tmp, &zv, &n); end = zv + n; - if (EXPECTED(!ht)) { + if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_BLACK)) { + ht = NULL; if (!n) return; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) return; } + } else { + GC_REF_SET_BLACK(ht); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -498,11 +501,14 @@ tail_call: ZVAL_OBJ(&tmp, obj); ht = get_gc(&tmp, &zv, &n); end = zv + n; - if (EXPECTED(!ht)) { + if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_GREY)) { + ht = NULL; if (!n) return; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) return; } + } else { + GC_REF_SET_COLOR(ht, GC_GREY); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -616,11 +622,14 @@ tail_call: ZVAL_OBJ(&tmp, obj); ht = get_gc(&tmp, &zv, &n); end = zv + n; - if (EXPECTED(!ht)) { + if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) != GC_GREY)) { + ht = NULL; if (!n) return; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) return; } + } else { + GC_REF_SET_COLOR(ht, GC_WHITE); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -791,7 +800,8 @@ tail_call: ZVAL_OBJ(&tmp, obj); ht = get_gc(&tmp, &zv, &n); end = zv + n; - if (EXPECTED(!ht)) { + if (EXPECTED(!ht) || UNEXPECTED(GC_REF_GET_COLOR(ht) == GC_BLACK)) { + ht = NULL; if (!n) return count; while (!Z_REFCOUNTED_P(--end)) { /* count non-refcounted for compatibility ??? */ @@ -800,6 +810,8 @@ tail_call: } if (zv == end) return count; } + } else { + GC_REF_SET_BLACK(ht); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) {