]> granicus.if.org Git - php/commitdiff
Fixed second part of the bug #78379 (Cast to object confuses GC, causes crash)
authorDmitry Stogov <dmitry@zend.com>
Fri, 9 Aug 2019 12:42:39 +0000 (15:42 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 9 Aug 2019 12:42:39 +0000 (15:42 +0300)
Zend/tests/bug78379_2.phpt [new file with mode: 0644]
Zend/zend_gc.c

diff --git a/Zend/tests/bug78379_2.phpt b/Zend/tests/bug78379_2.phpt
new file mode 100644 (file)
index 0000000..0a515a2
--- /dev/null
@@ -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
index 30ca4d0a2a89341e1768bd9eacf9d6fe9240e399..55f7271e3f914439d8063a6e07f570e0f36834be 100644 (file)
@@ -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)) {