]> granicus.if.org Git - python/commitdiff
Merged revisions 76665 via svnmerge from
authorMark Dickinson <dickinsm@gmail.com>
Fri, 4 Dec 2009 11:25:29 +0000 (11:25 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Fri, 4 Dec 2009 11:25:29 +0000 (11:25 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r76665 | mark.dickinson | 2009-12-04 11:24:38 +0000 (Fri, 04 Dec 2009) | 2 lines

  Avoid undefined behaviour due to overflow in i_divmod (Objects/intobject.c).
........

Objects/intobject.c

index ebe029eac4a746935cc23b9c1a980e0d3941dda5..406a45afefad1a28110fcfc6734c3b599eb26c3a 100644 (file)
@@ -584,7 +584,16 @@ i_divmod(register long x, register long y,
        if (y == -1 && UNARY_NEG_WOULD_OVERFLOW(x))
                return DIVMOD_OVERFLOW;
        xdivy = x / y;
-       xmody = x - xdivy * y;
+       /* xdiv*y can overflow on platforms where x/y gives floor(x/y)
+        * for x and y with differing signs. (This is unusual
+        * behaviour, and C99 prohibits it, but it's allowed by C89;
+        * for an example of overflow, take x = LONG_MIN, y = 5 or x =
+        * LONG_MAX, y = -5.)  However, x - xdivy*y is always
+        * representable as a long, since it lies strictly between
+        * -abs(y) and abs(y).  We add casts to avoid intermediate
+        * overflow.
+        */
+       xmody = (long)(x - (unsigned long)xdivy * y);
        /* If the signs of x and y differ, and the remainder is non-0,
         * C89 doesn't define whether xdivy is now the floor or the
         * ceiling of the infinitely precise quotient.  We want the floor,