]> granicus.if.org Git - php/commitdiff
Bug #39438 (Fatal error: Out of memory)
authorDmitry Stogov <dmitry@php.net>
Fri, 1 Dec 2006 20:02:00 +0000 (20:02 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 1 Dec 2006 20:02:00 +0000 (20:02 +0000)
Zend/tests/bug39438.phpt [new file with mode: 0755]
Zend/zend_alloc.c

diff --git a/Zend/tests/bug39438.phpt b/Zend/tests/bug39438.phpt
new file mode 100755 (executable)
index 0000000..e1ed8e8
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+Bug #39438 (Fatal error: Out of memory)
+--INI--
+memory_limit=16M
+--FILE--
+<?php
+$i=0;
+$test2=array(
+   'a1_teasermenu' => array(
+               'downloadcounter' => 2777,
+        'versions' => array(
+               '0.1.0' => array (
+                       'title' => 'A1 Teasermenu',
+                   'description' => 'Displays a teaser for advanced subpages or a selection of advanced pages',
+                   'state' => 'stable',
+                   'reviewstate' => 0,
+                   'category' => 'plugin',
+                   'downloadcounter' => 2787,
+                   'lastuploaddate' => 1088427240,
+                   'dependencies' => array (
+                         'depends' => array(
+                                 'typo3' =>'', 
+                                 'php' =>'', 
+                                 'cms' => ''
+                          ),           
+                         'conflicts' => array('' =>'')         
+                   ),          
+                       'authorname' => 'Mirko Balluff',
+                       'authoremail' => 'balluff@amt1.de',
+                       'ownerusername' => 'amt1',
+                       't3xfilemd5' => '3a4ec198b6ea8d0bc2d69d9b7400398f',
+               )
+               )
+       )
+);
+$test=array();
+while($i<1200) {       
+       $test[]=$test2;
+       $i++;
+}
+$out=serialize($test);
+echo "ok\n";
+?>
+--EXPECT--
+ok
index 3c869d243c768c5a788017295caf9a47a8a4169a..dff66ba52c0ceedb5a017c02449102418b109351 100644 (file)
@@ -472,6 +472,10 @@ static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_blo
                }
        } else {
                prev = &heap->free_buckets[0];
+               while (prev->next_free_block != &heap->free_buckets[0] &&
+                          ZEND_MM_FREE_BLOCK_SIZE(prev->next_free_block) < size) {
+                       prev = prev->next_free_block;
+               }
        }
        next = prev->next_free_block;
        mm_block->prev_free_block = prev;
@@ -1096,10 +1100,8 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
 
 static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
 {
-       size_t true_size, best_size = 0x7fffffff;
        zend_mm_free_block *p, *end, *best_fit = NULL;
-
-       true_size = ZEND_MM_TRUE_SIZE(size);
+       size_t true_size = ZEND_MM_TRUE_SIZE(size);
 
        if (ZEND_MM_SMALL_SIZE(true_size)) {
                size_t index = ZEND_MM_BUCKET_INDEX(true_size);
@@ -1152,16 +1154,14 @@ static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
 
        end = &heap->free_buckets[0];
        for (p = end->next_free_block; p != end; p = p->next_free_block) {
-               size_t s = ZEND_MM_FREE_BLOCK_SIZE(p);
-               if (s > true_size) {
-                       if (s < best_size) {    /* better fit */
+               if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size) {
+                       if (ZEND_MM_IS_FIRST_BLOCK(p) ||
+                           !ZEND_MM_IS_FIRST_BLOCK(ZEND_MM_PREV_BLOCK(p)) ||
+                               !ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(p)) ||
+                               p->next_free_block == end) {
                                best_fit = p;
-                               best_size = s;
+                               goto zend_mm_finished_searching_for_block;
                        }
-               } else if (s == true_size) {
-                       /* Found "big" free block of exactly the same size */
-                       best_fit = p;
-                       goto zend_mm_finished_searching_for_block;
                }
        }