[Python-checkins] r68589 - in python/trunk: Misc/NEWS Objects/stringlib/transmogrify.h

antoine.pitrou python-checkins at python.org
Wed Jan 14 00:13:52 CET 2009


Author: antoine.pitrou
Date: Wed Jan 14 00:13:52 2009
New Revision: 68589

Log:
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.



Modified:
   python/trunk/Misc/NEWS
   python/trunk/Objects/stringlib/transmogrify.h

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Wed Jan 14 00:13:52 2009
@@ -12,6 +12,10 @@
 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.
 

Modified: python/trunk/Objects/stringlib/transmogrify.h
==============================================================================
--- python/trunk/Objects/stringlib/transmogrify.h	(original)
+++ python/trunk/Objects/stringlib/transmogrify.h	Wed Jan 14 00:13:52 2009
@@ -22,76 +22,69 @@
 {
     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;
 }
 


More information about the Python-checkins mailing list