]> granicus.if.org Git - python/commitdiff
Issue #9530: Fix undefined behaviour due to signed overflow in Python/formatter_unico...
authorMark Dickinson <mdickinson@enthought.com>
Thu, 1 Dec 2011 15:27:04 +0000 (15:27 +0000)
committerMark Dickinson <mdickinson@enthought.com>
Thu, 1 Dec 2011 15:27:04 +0000 (15:27 +0000)
Python/formatter_unicode.c

index fda79fc6572c69aefc9088235cf38460e65c4b6e..6deb3cd7fe85f239319539ad4783e6622f649df2 100644 (file)
@@ -51,7 +51,7 @@ static int
 get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end,
                   Py_ssize_t *result)
 {
-    Py_ssize_t accumulator, digitval, oldaccumulator;
+    Py_ssize_t accumulator, digitval;
     int numdigits;
     accumulator = numdigits = 0;
     for (;;(*pos)++, numdigits++) {
@@ -61,19 +61,17 @@ get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end,
         if (digitval < 0)
             break;
         /*
-           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;
     }
     *result = accumulator;
     return numdigits;