diff options
author | Dmitry Stogov <dmitry@zend.com> | 2019-08-09 15:58:16 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2019-08-09 15:58:16 +0300 |
commit | 22d23e08c927f07b0bc7ed72dbfc3d8ea79bed7c (patch) | |
tree | 064c72716ba6b9f6360b26d1809c76280383b358 | |
parent | 21a0a28fd09fc5b0df6a7dc139f0fddbdcec7b62 (diff) | |
parent | 6b1cc1252e73e51e53194c8c65e3d2302bc83dca (diff) | |
download | php-git-22d23e08c927f07b0bc7ed72dbfc3d8ea79bed7c.tar.gz |
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)
-rw-r--r-- | Zend/tests/bug78379_2.phpt | 19 | ||||
-rw-r--r-- | Zend/zend_gc.c | 20 |
2 files changed, 35 insertions, 4 deletions
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-- +<?php +class E {} +function f() { + $e1 = new E; + $e2 = new E; + $a = ['e2' => $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 60fa7fdd15..d1fcbf00ca 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -701,11 +701,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_CHECK_COLOR(ht, GC_BLACK))) { + ht = NULL; if (!n) goto next; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } + } else { + GC_REF_SET_BLACK(ht); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -820,11 +823,14 @@ static void gc_mark_grey(zend_refcounted *ref, gc_stack *stack) ZVAL_OBJ(&tmp, obj); ht = get_gc(&tmp, &zv, &n); end = zv + n; - if (EXPECTED(!ht)) { + if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_GREY))) { + ht = NULL; if (!n) goto next; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } + } else { + GC_REF_SET_COLOR(ht, GC_GREY); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -1010,11 +1016,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_CHECK_COLOR(ht, GC_GREY))) { + ht = NULL; if (!n) goto next; while (!Z_REFCOUNTED_P(--end)) { if (zv == end) goto next; } + } else { + GC_REF_SET_COLOR(ht, GC_WHITE); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { @@ -1181,7 +1190,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta ZVAL_OBJ(&tmp, obj); ht = get_gc(&tmp, &zv, &n); end = zv + n; - if (EXPECTED(!ht)) { + if (EXPECTED(!ht) || UNEXPECTED(GC_REF_CHECK_COLOR(ht, GC_BLACK))) { + ht = NULL; if (!n) goto next; while (!Z_REFCOUNTED_P(--end)) { /* count non-refcounted for compatibility ??? */ @@ -1190,6 +1200,8 @@ static int gc_collect_white(zend_refcounted *ref, uint32_t *flags, gc_stack *sta } if (zv == end) goto next; } + } else { + GC_REF_SET_BLACK(ht); } while (zv != end) { if (Z_REFCOUNTED_P(zv)) { |