]> granicus.if.org Git - php/commitdiff
Fixed bug #78379 (Cast to object confuses GC, causes crash)
authorDmitry Stogov <dmitry@zend.com>
Thu, 8 Aug 2019 07:00:39 +0000 (10:00 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 8 Aug 2019 07:00:39 +0000 (10:00 +0300)
NEWS
Zend/tests/bug78379.phpt [new file with mode: 0644]
Zend/zend_object_handlers.c

diff --git a/NEWS b/NEWS
index a4e4793e857ad02dc2f68fdf7434d60f43888b74..f245fa8b16cc6a7d4b888abfe679a6743e9a4dc8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ PHP                                                                        NEWS
 
 - Core:
   . Fixed bug #78363 (Buffer overflow in zendparse). (Nikita)
+  . Fixed bug #78379 (Cast to object confuses GC, causes crash). (Dmitry)
 
 - Curl:
   . Fixed bug #77946 (Bad cURL resources returned by curl_multi_info_read()).
diff --git a/Zend/tests/bug78379.phpt b/Zend/tests/bug78379.phpt
new file mode 100644 (file)
index 0000000..e48e9b7
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #78379 (Cast to object confuses GC, causes crash)
+--INI--
+opcache.enable=0
+--FILE--
+<?php
+class C {
+       public function __construct() {
+               $this->p = (object)["x" => [1]];
+       }
+}
+class E {
+}
+$e = new E;
+$e->f = new E;
+$e->f->e = $e;
+$e->a = new C;
+$e = null;
+gc_collect_cycles();
+var_dump(new C);
+?>
+--EXPECTF--
+object(C)#%d (1) {
+  ["p"]=>
+  object(stdClass)#%d (1) {
+    ["x"]=>
+    array(1) {
+      [0]=>
+      int(1)
+    }
+  }
+}
index 1d4ee75a64b2179e62cbd70368c46e419397287f..d0555c003104b61b686191d46e0f790489364773 100644 (file)
@@ -138,6 +138,11 @@ ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n) /* {{{ *
                if (zobj->properties) {
                        *table = NULL;
                        *n = 0;
+                       if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)
+                        && EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
+                               GC_REFCOUNT(zobj->properties)--;
+                               zobj->properties = zend_array_dup(zobj->properties);
+                       }
                        return zobj->properties;
                } else {
                        *table = zobj->properties_table;