]> granicus.if.org Git - php/commitdiff
Fixed bug #44069 (Huge memory usage with concatenation using . instead of .=)
authorDmitry Stogov <dmitry@php.net>
Thu, 14 Feb 2008 14:47:25 +0000 (14:47 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 14 Feb 2008 14:47:25 +0000 (14:47 +0000)
NEWS
Zend/tests/bug44069.phpt [new file with mode: 0644]
Zend/zend_alloc.c

diff --git a/NEWS b/NEWS
index 5655e24f868693f816e00ac321b952b05bf39f1a..9e39610d422cf0170e8599eb0e0a809c4cbb921f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@ PHP                                                                        NEWS
   which to group by data is specified. (Ilia)
 - Upgraded PCRE to version 7.6 (Nuno)
 
+- Fixed bug #44069 (Huge memory usage with concatenation using . instead of
+  .=). (Dmitry)
 - Fixed bug #44046 (crash inside array_slice() function with an invalid
   by-ref offset). (Ilia)
 - Fixed bug #44028 (crash inside stream_socket_enable_crypto() when enabling
diff --git a/Zend/tests/bug44069.phpt b/Zend/tests/bug44069.phpt
new file mode 100644 (file)
index 0000000..75beaaf
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Bug #44069 (Huge memory usage with concatenation using . instead of .=)
+--FILE--
+<?php
+$array = array();
+$newstring = "";
+$string = str_repeat('This is a teststring.', 50);
+for($i = 1; $i <= 2000; $i++)
+{
+//     $newstring .= $string; //This uses an expected amount of mem.
+       $newstring = $newstring . $string; //This uses very much mem.
+
+       for($j = 1; $j <= 10; $j++)
+       {
+               $array[] = 'test';
+       }
+}
+echo "ok\n";
+?>
+--EXPECT--
+ok
index 8c53611e01300eb356f948d6f2b1d74378ae6dcf..d48c29c6ec0973f5abfd905fbef09eeac642d40a 100644 (file)
@@ -1747,6 +1747,7 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
        size_t remaining_size;
        size_t segment_size;
        zend_mm_segment *segment;
+       int keep_rest = 0;
 
        if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) {
                size_t index = ZEND_MM_BUCKET_INDEX(true_size);
@@ -1815,6 +1816,7 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
                           segment must have header "size" and trailer "guard" block */
                        segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE;
                        segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1);
+                       keep_rest = 1;
                } else {
                        segment_size = heap->block_size;
                }
@@ -1894,7 +1896,11 @@ zend_mm_finished_searching_for_block:
                ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size);
 
                /* add the new free block to the free list */
-               zend_mm_add_to_free_list(heap, new_free_block);
+               if (EXPECTED(!keep_rest)) {
+                       zend_mm_add_to_free_list(heap, new_free_block);
+               } else {
+                       zend_mm_add_to_rest_list(heap, new_free_block);
+               }
        }
 
        ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1);