[commit: ghc] master: rts: fix Windows megablock allocator (676f1f2)

git at git.haskell.org git at git.haskell.org
Thu Nov 22 18:44:48 UTC 2018


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/676f1f2d2eb39740fe5d88e72f6aa8e89cb0ebc0/ghc

>---------------------------------------------------------------

commit 676f1f2d2eb39740fe5d88e72f6aa8e89cb0ebc0
Author: Tamar Christina <tamar at zhox.com>
Date:   Thu Nov 22 11:47:10 2018 -0500

    rts: fix Windows megablock allocator
    
    The megablock allocator does not currently check that after aligning the
    free region if it still has enough space to actually do the allocation.
    
    This causes it to return a memory region which it didn't fully allocate
    itself.  Even worse, it can cause it to return a block with a region
    that will be present in two allocation pools.
    
    This causes if you're lucky an error from the OS that you're committing
    memory that has never been reserved, or causes random heap corruption.
    
    This change makes it consider the alignment as well.
    
    Test Plan: ./validate , testcase testmblockalloc
    
    Reviewers: bgamari, erikd, simonmar
    
    Reviewed By: simonmar
    
    Subscribers: rwbarton, carter
    
    Differential Revision: https://phabricator.haskell.org/D5363


>---------------------------------------------------------------

676f1f2d2eb39740fe5d88e72f6aa8e89cb0ebc0
 rts/win32/OSMem.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/rts/win32/OSMem.c b/rts/win32/OSMem.c
index c62ee3b..57997b1 100644
--- a/rts/win32/OSMem.c
+++ b/rts/win32/OSMem.c
@@ -144,8 +144,11 @@ findFreeBlocks(uint32_t n) {
     temp.next=free_blocks; temp.base=0; temp.size=0;
     prev=&temp;
     /* TODO: Don't just take first block, find smallest sufficient block */
-    for( ; it!=0 && it->size<required_size; prev=it, it=it->next ) {}
-    if(it!=0) {
+    for ( ; it; prev=it, it=it->next )
+      {
+        if (!it || it->size < required_size)
+          continue;
+
         if( (((W_)it->base) & MBLOCK_MASK) == 0) { /* MBlock aligned */
             ret = (void*)it->base;
             if(it->size==required_size) {
@@ -155,24 +158,30 @@ findFreeBlocks(uint32_t n) {
                 it->base += required_size;
                 it->size -=required_size;
             }
+            break;
         } else {
             char* need_base;
             block_rec* next;
             int new_size;
             need_base =
                 (char*)(((W_)it->base) & ((W_)~MBLOCK_MASK)) + MBLOCK_SIZE;
+            new_size = need_base - it->base;
+            /* Make sure that after alignment we have enough space.  */
+            W_ total_size = new_size + required_size;
+            if (total_size > it->size)
+              continue;
             next = (block_rec*)stgMallocBytes(
                     sizeof(block_rec)
                     , "getMBlocks: findFreeBlocks: splitting");
-            new_size = need_base - it->base;
             next->base = need_base +required_size;
-            next->size = it->size - (new_size+required_size);
+            next->size = it->size - total_size;
             it->size = new_size;
             next->next = it->next;
             it->next = next;
             ret=(void*)need_base;
+            break;
         }
-    }
+      }
     free_blocks=temp.next;
     return ret;
 }



More information about the ghc-commits mailing list