summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-08-09 15:58:16 +0300
committerDmitry Stogov <dmitry@zend.com>2019-08-09 15:58:16 +0300
commit22d23e08c927f07b0bc7ed72dbfc3d8ea79bed7c (patch)
tree064c72716ba6b9f6360b26d1809c76280383b358
parent21a0a28fd09fc5b0df6a7dc139f0fddbdcec7b62 (diff)
parent6b1cc1252e73e51e53194c8c65e3d2302bc83dca (diff)
downloadphp-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.phpt19
-rw-r--r--Zend/zend_gc.c20
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)) {