Cast some more nats to StgWord to be on the safe side
authorSimon Marlow <marlowsd@gmail.com>
Thu, 24 Jun 2010 10:57:00 +0000 (10:57 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Thu, 24 Jun 2010 10:57:00 +0000 (10:57 +0000)
And add a comment about the dangers of int overflow

rts/sm/BlockAlloc.c

index 484c0d4..ba9220a 100644 (file)
@@ -118,6 +118,16 @@ static void  initMBlock(void *mblock);
 
   --------------------------------------------------------------------------- */
 
+/* ---------------------------------------------------------------------------
+   WATCH OUT FOR OVERFLOW
+
+   Be very careful with integer overflow here.  If you have an
+   expression like (n_blocks * BLOCK_SIZE), and n_blocks is an int or
+   a nat, then it will very likely overflow on a 64-bit platform.
+   Always cast to StgWord (or W_ for short) first: ((W_)n_blocks * BLOCK_SIZE).
+
+  --------------------------------------------------------------------------- */
+
 #define MAX_FREE_LIST 9
 
 // In THREADED_RTS mode, the free list is protected by sm_mutex.
@@ -337,7 +347,7 @@ allocGroup (nat n)
 
     if (ln == MAX_FREE_LIST) {
 #if 0
-        if ((mblocks_allocated * MBLOCK_SIZE_W - n_alloc_blocks * BLOCK_SIZE_W) > (1024*1024)/sizeof(W_)) {
+        if (((W_)mblocks_allocated * MBLOCK_SIZE_W - (W_)n_alloc_blocks * BLOCK_SIZE_W) > (1024*1024)/sizeof(W_)) {
             debugBelch("Fragmentation, wanted %d blocks:", n);
             RtsFlags.DebugFlags.block_alloc = 1;
             checkFreeListSanity();
@@ -472,7 +482,7 @@ freeGroup(bdescr *p)
   p->gen = NULL;
   p->gen_no = 0;
   /* fill the block group with garbage if sanity checking is on */
-  IF_DEBUG(sanity,memset(p->start, 0xaa, p->blocks * BLOCK_SIZE));
+  IF_DEBUG(sanity,memset(p->start, 0xaa, (W_)p->blocks * BLOCK_SIZE));
 
   if (p->blocks == 0) barf("freeGroup: block size is zero");
 
@@ -586,7 +596,7 @@ splitBlockGroup (bdescr *bd, nat blocks)
         low_mblocks = 1 + (blocks - BLOCKS_PER_MBLOCK) / (MBLOCK_SIZE / BLOCK_SIZE);
         high_mblocks = (bd->blocks - blocks) / (MBLOCK_SIZE / BLOCK_SIZE);
 
-        new_mblock = (void *) ((P_)MBLOCK_ROUND_DOWN(bd) + low_mblocks * MBLOCK_SIZE_W);
+        new_mblock = (void *) ((P_)MBLOCK_ROUND_DOWN(bd) + (W_)low_mblocks * MBLOCK_SIZE_W);
         initMBlock(new_mblock);
         new_bd = FIRST_BDESCR(new_mblock);
         new_bd->blocks = MBLOCK_GROUP_BLOCKS(high_mblocks);