Ticket #5838 (closed bug: fixed)

Opened 16 months ago

Last modified 15 months ago

integer overflow in rts/RtsUtils:heapOverflow()

Reported by: hvr Owned by: simonmar
Priority: high Milestone: 7.4.2
Component: Runtime System Version: 7.2.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: x86_64 (amd64)
Type of failure: Incorrect result at runtime Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

When failing with a heap exhaustion, the RTS truncates the reported current maximum heap size modulo 232, e.g.

$ ghc +RTS -M4G -RTS -e 'sum [1..]'
Heap exhausted;
Current maximum heap size is 0 bytes (0 MB);
use `+RTS -M<size>' to increase it.

This is most probably due to OutOfHeapHook() already being called with the truncated value from heapOverflow():

void
heapOverflow(void)
{
    if (!heap_overflow)
    {
        /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
        OutOfHeapHook(0/*unknown request size*/,
                      RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);

        heap_overflow = rtsTrue;
    }
}

which multiplies RtsFlags.GcFlags.maxHeapSize and BLOCK_SIZE whose type are 32-bit unsigned ints, causing the result to be wrapped again into an unsigned int, whereas the result should be upcasted to a long unsigned int (which at least on 64bit archs would be equivalent to a C99 uint64_t)

Change History

Changed 16 months ago by hvr

Unless I've forgotten everything about C99, the following untested(!) modification should fix it:

  • rts/RtsUtils.c

    diff --git a/rts/RtsUtils.c b/rts/RtsUtils.c
    index e04b984..b880f8c 100644
    a b  
    130130    { 
    131131        /* don't fflush(stdout); WORKAROUND bug in Linux glibc */ 
    132132        OutOfHeapHook(0/*unknown request size*/, 
    133                       RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE); 
     133                      (lnat)RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE); 
    134134 
    135135        heap_overflow = rtsTrue; 
    136136    } 

Changed 16 months ago by igloo

  • status changed from new to patch
  • difficulty set to Unknown
  • milestone set to 7.4.2

Thanks for the report and patch.

Changed 16 months ago by simonmar

  • owner set to simonmar
  • priority changed from normal to high

Changed 16 months ago by simonmar

  • status changed from patch to merge

Fixed (but I got the ticket number wrong in the commit log):

commit bf456a09f9ef68436db48eb5ea25193d3b2f2ed5

Author: Simon Marlow <marlowsd@gmail.com>
Date:   Thu Feb 2 10:28:34 2012 +0000

    avoid 32-bit integer overflow (#5831)

Changed 15 months ago by pcapriotti

  • status changed from merge to closed
  • resolution set to fixed

Merged as 11b56ff206bfa99cee641a44d07831914f788c8a.

Note: See TracTickets for help on using tickets.