[Python-checkins] cpython: Issue #1621: Fix undefined behaviour from signed overflow in datetime module

mark.dickinson python-checkins at python.org
Sun Sep 25 16:35:02 CEST 2011


http://hg.python.org/cpython/rev/3fb9464f9b02
changeset:   72468:3fb9464f9b02
user:        Mark Dickinson <mdickinson at enthought.com>
date:        Sun Sep 25 15:34:32 2011 +0100
summary:
  Issue #1621: Fix undefined behaviour from signed overflow in datetime module hashes, array and list iterations, and get_integer (stringlib/string_format.h)

files:
  Modules/_datetimemodule.c         |   8 ++++----
  Modules/arraymodule.c             |   2 +-
  Objects/listobject.c              |   6 +++---
  Objects/stringlib/string_format.h |  14 ++++++--------
  4 files changed, 14 insertions(+), 16 deletions(-)


diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -2746,13 +2746,13 @@
 generic_hash(unsigned char *data, int len)
 {
     register unsigned char *p;
-    register Py_hash_t x;
+    register Py_uhash_t x;
 
     p = (unsigned char *) data;
-    x = *p << 7;
+    x = (Py_uhash_t)*p << 7;
     while (--len >= 0)
-        x = (1000003*x) ^ *p++;
-    x ^= len;
+        x = (1000003U*x) ^ (Py_uhash_t)*p++;
+    x ^= (Py_uhash_t)len;
     if (x == -1)
         x = -2;
 
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -2351,7 +2351,7 @@
                 self->ob_item + (cur + 1) * itemsize,
                 lim * itemsize);
         }
-        cur = start + slicelength * step;
+        cur = start + (size_t)slicelength * step;
         if (cur < (size_t)Py_SIZE(self)) {
             memmove(self->ob_item + (cur-slicelength) * itemsize,
                 self->ob_item + cur * itemsize,
diff --git a/Objects/listobject.c b/Objects/listobject.c
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2434,7 +2434,7 @@
             src = self->ob_item;
             dest = ((PyListObject *)result)->ob_item;
             for (cur = start, i = 0; i < slicelength;
-                 cur += step, i++) {
+                 cur += (size_t)step, i++) {
                 it = src[cur];
                 Py_INCREF(it);
                 dest[i] = it;
@@ -2525,7 +2525,7 @@
                     self->ob_item + cur + 1,
                     lim * sizeof(PyObject *));
             }
-            cur = start + slicelength*step;
+            cur = start + (size_t)slicelength * step;
             if (cur < (size_t)Py_SIZE(self)) {
                 memmove(self->ob_item + cur - slicelength,
                     self->ob_item + cur,
@@ -2589,7 +2589,7 @@
             selfitems = self->ob_item;
             seqitems = PySequence_Fast_ITEMS(seq);
             for (cur = start, i = 0; i < slicelength;
-                 cur += step, i++) {
+                 cur += (size_t)step, i++) {
                 garbage[i] = selfitems[cur];
                 ins = seqitems[i];
                 Py_INCREF(ins);
diff --git a/Objects/stringlib/string_format.h b/Objects/stringlib/string_format.h
--- a/Objects/stringlib/string_format.h
+++ b/Objects/stringlib/string_format.h
@@ -209,19 +209,17 @@
         if (digitval < 0)
             return -1;
         /*
-           This trick was copied from old Unicode format code.  It's cute,
-           but would really suck on an old machine with a slow divide
-           implementation.  Fortunately, in the normal case we do not
-           expect too many digits.
+           Detect possible overflow before it happens:
+
+              accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if
+              accumulator > (PY_SSIZE_T_MAX - digitval) / 10.
         */
-        oldaccumulator = accumulator;
-        accumulator *= 10;
-        if ((accumulator+10)/10 != oldaccumulator+1) {
+        if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) {
             PyErr_Format(PyExc_ValueError,
                          "Too many decimal digits in format string");
             return -1;
         }
-        accumulator += digitval;
+        accumulator = accumulator * 10 + digitval;
     }
     return accumulator;
 }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list