diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-12-04 11:24:38 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-12-04 11:24:38 (GMT) |
commit | 1691025ff2f9074ab5eedff17a030e3127eb55b8 (patch) | |
tree | 498d0f84cd7451aefbf0650217bab96f2b62cc1b /Objects | |
parent | 820b0ea36c9f2ad2c940f157fb69c045c6a0ad96 (diff) | |
download | cpython-1691025ff2f9074ab5eedff17a030e3127eb55b8.zip cpython-1691025ff2f9074ab5eedff17a030e3127eb55b8.tar.gz cpython-1691025ff2f9074ab5eedff17a030e3127eb55b8.tar.bz2 |
Avoid undefined behaviour due to overflow in i_divmod (Objects/intobject.c).
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/intobject.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/Objects/intobject.c b/Objects/intobject.c index 43dedf2..b03ef70 100644 --- a/Objects/intobject.c +++ b/Objects/intobject.c @@ -580,7 +580,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, |