[GHC] #8695: Arithmetic overflow from (minBound :: Int) `quot` (-1)

GHC ghc-devs at haskell.org
Tue Jan 28 11:10:21 UTC 2014


#8695: Arithmetic overflow from (minBound :: Int) `quot` (-1)
------------------------------------------------+--------------------------
        Reporter:  rleslie                      |            Owner:
            Type:  bug                          |           Status:  new
        Priority:  normal                       |        Milestone:
       Component:  libraries/haskell2010        |          Version:  7.6.3
      Resolution:                               |         Keywords:
Operating System:  Unknown/Multiple             |     Architecture:
 Type of failure:  Incorrect result at runtime  |  Unknown/Multiple
       Test Case:                               |       Difficulty:
        Blocking:                               |  Unknown
                                                |       Blocked By:
                                                |  Related Tickets:
------------------------------------------------+--------------------------

Comment (by rleslie):

 Replying to [comment:6 hvr]:
 > Fwiw as a precedent, the following C99 program when compiled with gcc or
 clang, and executed on Linux results in a runtime exception as well:
 >
 > {{{#!c
 > #include <stdio.h>
 > #include <inttypes.h>
 >
 > int main(int argc, char *argv[])
 > {
 >   volatile int32_t a = INT32_MIN;
 >   volatile int32_t b = -1;
 >   volatile int32_t c = a / b;
 >   printf("%" PRId32 "\n", c);
 >   return 0;
 > }
 > }}}

 In C, the behavior of signed integer operations that overflow is
 undefined, so this is not unexpected.

 In Haskell, we have Data.Int which declares that signed fixed-precision
 integer arithmetic operations are performed modulo 2!^n, and thus do not
 overflow. Except {{{minBound `quot` (-1)}}} violates this rule.

 > Given that `quot`/`div` is already a partial function due to div-by-
 zero, and {{{minBound `quot` -1}}} being the only special case (beside
 div-by-zero) for (`quot`/`div`) which leads to a result outside the
 `[minBound..maxBound]` range, so I'd rather have this exception thrown
 than to have a program which didn't take into account this non-obvious
 overflow silently misbehaving due to a flipped sign (as you pointed out
 yourself if I understood you correctly, but then dismissed it as not being
 worth an exception).

 The same argument could be made for many other arithmetic operations, like
 `minBound * (-1)`, as well as `minBound - 1`, `maxBound + 1`, etc. I don't
 see any reason to have a special case for {{{minBound `quot` (-1)}}}.

 It happens that the only reason I discovered this behavior and have
 reported it as a bug is that it unexpectedly caused a program to abort
 rather than return the (expected) modulo arithmetic result. So a non-
 obvious and unexpected exception can equally cause a program to misbehave.
 This can be especially devastating in a server application.

 A program that is sensitive to overflow conditions probably ought not be
 using fixed-precision integers in the first place; `Integer` would be a
 better choice.

 But despite what you or I might prefer, the fact remains that modulo
 arithmetic is the documented behavior for signed fixed-precision integers,
 so I still tend to view the exception thrown by {{{minBound `quot` (-1)}}}
 as a bug.

 > PS: I believe one may as well argue (as an academic exercise) in a
 parallel way, that `quotRem` by 0 could be assigned a value that satisfies
 the laws from § 6.4.2 as well, thus making it a total function.

 While that might be an interesting exercise, the laws I quoted only apply
 “if `y` is non-zero”. So I argue the laws ''demand'' satisfaction when `y`
 is `(-1)`.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8695#comment:7>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list