summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMark Dickinson <dickinsm@gmail.com>2009-12-04 11:25:29 (GMT)
committerMark Dickinson <dickinsm@gmail.com>2009-12-04 11:25:29 (GMT)
commit3f8707c23f419fabd1ff3e8e9243afc358a546e8 (patch)
tree2a0134f49cb2d0164d574343815120adda828ba1 /Objects
parent1b479f24dcc543cc3d992ddb7ffa2c01a7559ebc (diff)
downloadcpython-3f8707c23f419fabd1ff3e8e9243afc358a546e8.zip
cpython-3f8707c23f419fabd1ff3e8e9243afc358a546e8.tar.gz
cpython-3f8707c23f419fabd1ff3e8e9243afc358a546e8.tar.bz2
Merged revisions 76665 via svnmerge from
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). ........
Diffstat (limited to 'Objects')
-rw-r--r--Objects/intobject.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/Objects/intobject.c b/Objects/intobject.c
index ebe029e..406a45a 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -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,