]> granicus.if.org Git - python/commitdiff
fix expandtabs overflow detection to be consistent and not rely on signed overflow
authorBenjamin Peterson <benjamin@python.org>
Sun, 30 Mar 2014 23:47:57 +0000 (19:47 -0400)
committerBenjamin Peterson <benjamin@python.org>
Sun, 30 Mar 2014 23:47:57 +0000 (19:47 -0400)
Objects/stringlib/transmogrify.h

index 1e132e54aa60cffe8b85bcaeb0f0d8b295a423cb..be595a62ef4b401de7d5e50e6bf25b8f4c2819db 100644 (file)
@@ -15,7 +15,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
 {
     const char *e, *p;
     char *q;
-    size_t i, j;
+    Py_ssize_t i, j;
     PyObject *u;
     int tabsize = 8;
     
@@ -25,35 +25,31 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
     /* First pass: determine size of output string */
     i = j = 0;
     e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
-    for (p = STRINGLIB_STR(self); p < e; p++)
+    for (p = STRINGLIB_STR(self); p < e; p++) {
         if (*p == '\t') {
             if (tabsize > 0) {
-                j += tabsize - (j % tabsize);
-                if (j > PY_SSIZE_T_MAX) {
-                    PyErr_SetString(PyExc_OverflowError,
-                                    "result is too long");
-                    return NULL;
-                }
+                Py_ssize_t incr = tabsize - (j % tabsize);
+                if (j > PY_SSIZE_T_MAX - incr)
+                    goto overflow;
+                j += incr;
             }
         }
         else {
+            if (j > PY_SSIZE_T_MAX - 1)
+                goto overflow;
             j++;
             if (*p == '\n' || *p == '\r') {
+                if (i > PY_SSIZE_T_MAX - j)
+                    goto overflow;
                 i += j;
                 j = 0;
-                if (i > PY_SSIZE_T_MAX) {
-                    PyErr_SetString(PyExc_OverflowError,
-                                    "result is too long");
-                    return NULL;
-                }
             }
         }
-    
-    if ((i + j) > PY_SSIZE_T_MAX) {
-        PyErr_SetString(PyExc_OverflowError, "result is too long");
-        return NULL;
     }
     
+    if (i > PY_SSIZE_T_MAX - j)
+        goto overflow;
+    
     /* Second pass: create output string and fill it */
     u = STRINGLIB_NEW(NULL, i + j);
     if (!u)
@@ -62,7 +58,7 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
     j = 0;
     q = STRINGLIB_STR(u);
     
-    for (p = STRINGLIB_STR(self); p < e; p++)
+    for (p = STRINGLIB_STR(self); p < e; p++) {
         if (*p == '\t') {
             if (tabsize > 0) {
                 i = tabsize - (j % tabsize);
@@ -77,8 +73,12 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
             if (*p == '\n' || *p == '\r')
                 j = 0;
         }
-    
+    }
+
     return u;
+  overflow:
+    PyErr_SetString(PyExc_OverflowError, "result too long");
+    return NULL;
 }
 
 Py_LOCAL_INLINE(PyObject *)