]> granicus.if.org Git - php/commitdiff
Fixed bug #78010
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 15 Jul 2019 10:00:30 +0000 (12:00 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 15 Jul 2019 10:00:30 +0000 (12:00 +0200)
Prevent the gc_info from becoming all zero for a registered root
by setting the top bit to one for compressed root addresses.

Zend/tests/bug78010.phpt [new file with mode: 0644]
Zend/zend_gc.c

diff --git a/Zend/tests/bug78010.phpt b/Zend/tests/bug78010.phpt
new file mode 100644 (file)
index 0000000..a9ebc37
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #78010: Segmentation fault during GC
+--INI--
+memory_limit=2G
+--FILE--
+<?php
+
+class foo
+{
+    public function __construct()
+    {
+        $this->x = $this;
+
+        for ($i = 0; $i < 898; $i++) { //Will not trigger with <898
+            $obj = [new stdClass, new stdClass]; //This must have at least 2 elements
+            $this->y[] = $obj;
+        }
+    }
+}
+
+for ($i = 0; $i < 2; ++$i) { //This must run >=2 (increasing the number of elements in the array *2 will not do)
+    $x = []; //This must be reset
+    foreach (array_fill(0, 389, 'x') as &$params) { //Will not trigger <389
+        $x[] = new foo;
+    }
+}
+
+echo "Completed\n";
+
+?>
+--EXPECT--
+Completed
index 5486452581402d33f6e6876ea4411cf3aec64872..7280fdd20dfe07d9a945a4285630c2cf4f835446 100644 (file)
 #define GC_DEFAULT_BUF_SIZE  (16 * 1024)
 #define GC_BUF_GROW_STEP     (128 * 1024)
 
-#define GC_MAX_UNCOMPRESSED  (1024 * 1024)
+#define GC_MAX_UNCOMPRESSED  (512 * 1024)
 #define GC_MAX_BUF_SIZE      0x40000000
 
 #define GC_THRESHOLD_DEFAULT 10000
@@ -314,7 +314,10 @@ static void gc_stack_free(gc_stack *stack)
 
 static zend_always_inline uint32_t gc_compress(uint32_t idx)
 {
-       return idx % GC_MAX_UNCOMPRESSED;
+       if (EXPECTED(idx < GC_MAX_UNCOMPRESSED)) {
+               return idx;
+       }
+       return (idx % GC_MAX_UNCOMPRESSED) | GC_MAX_UNCOMPRESSED;
 }
 
 static zend_always_inline gc_root_buffer* gc_decompress(zend_refcounted *ref, uint32_t idx)