]> granicus.if.org Git - python/commitdiff
Issue #4935: The overflow checking code in the expandtabs() method common
authorAntoine Pitrou <solipsis@pitrou.net>
Tue, 13 Jan 2009 22:59:11 +0000 (22:59 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Tue, 13 Jan 2009 22:59:11 +0000 (22:59 +0000)
to str, bytes and bytearray could be optimized away by the compiler (*), letting
the interpreter segfault instead of raising an error.

(*) or at least it is our interpretation

Misc/NEWS
Objects/stringlib/transmogrify.h

index 6695a242aeaf79d358393cceafcb4b9efeabc212..ac308973a17972e9bc3189f8c9b183dca6746b61 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 3.1 alpha 0
 Core and Builtins
 -----------------
 
+- Issue #4935: The overflow checking code in the expandtabs() method common
+  to str, bytes and bytearray could be optimized away by the compiler, letting
+  the interpreter segfault instead of raising an error.
+
 - Issue #3720: Fix a crash when an iterator modifies its class and removes its
   __next__ method.
 
index fe478c358cd6cb5f12aad257fbe51656b1c143e3..7dc81776ab395e4c9886817b699fba778d8eadbe 100644 (file)
@@ -22,76 +22,69 @@ stringlib_expandtabs(PyObject *self, PyObject *args)
 {
     const char *e, *p;
     char *q;
-    Py_ssize_t i, j, old_j;
+    size_t i, j;
     PyObject *u;
     int tabsize = 8;
-
+    
     if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
-       return NULL;
-
+        return NULL;
+    
     /* First pass: determine size of output string */
-    i = j = old_j = 0;
+    i = j = 0;
     e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
     for (p = STRINGLIB_STR(self); p < e; p++)
         if (*p == '\t') {
-           if (tabsize > 0) {
-               j += tabsize - (j % tabsize);
-                /* XXX: this depends on a signed integer overflow to < 0 */
-                /* C compilers, including gcc, do -NOT- guarantee this. */
-               if (old_j > j) {
-                   PyErr_SetString(PyExc_OverflowError,
-                                   "result is too long");
-                   return NULL;
-               }
-               old_j = j;
+            if (tabsize > 0) {
+                j += tabsize - (j % tabsize);
+                if (j > PY_SSIZE_T_MAX) {
+                    PyErr_SetString(PyExc_OverflowError,
+                                    "result is too long");
+                    return NULL;
+                }
             }
-       }
+        }
         else {
             j++;
             if (*p == '\n' || *p == '\r') {
                 i += j;
-                old_j = j = 0;
-                /* XXX: this depends on a signed integer overflow to < 0 */
-                /* C compilers, including gcc, do -NOT- guarantee this. */
-                if (i < 0) {
+                j = 0;
+                if (i > PY_SSIZE_T_MAX) {
                     PyErr_SetString(PyExc_OverflowError,
                                     "result is too long");
                     return NULL;
                 }
             }
         }
-
-    if ((i + j) < 0) {
-        /* XXX: this depends on a signed integer overflow to < 0 */
-        /* C compilers, including gcc, do -NOT- guarantee this. */
+    
+    if ((i + j) > PY_SSIZE_T_MAX) {
         PyErr_SetString(PyExc_OverflowError, "result is too long");
         return NULL;
     }
-
+    
     /* Second pass: create output string and fill it */
     u = STRINGLIB_NEW(NULL, i + j);
     if (!u)
         return NULL;
-
+    
     j = 0;
     q = STRINGLIB_STR(u);
-
+    
     for (p = STRINGLIB_STR(self); p < e; p++)
         if (*p == '\t') {
-           if (tabsize > 0) {
-               i = tabsize - (j % tabsize);
-               j += i;
-               while (i--)
-                   *q++ = ' ';
-           }
-       }
-       else {
+            if (tabsize > 0) {
+                i = tabsize - (j % tabsize);
+                j += i;
+                while (i--)
+                    *q++ = ' ';
+            }
+        }
+        else {
             j++;
-           *q++ = *p;
+            *q++ = *p;
             if (*p == '\n' || *p == '\r')
                 j = 0;
         }
-
+    
     return u;
 }