[Python-checkins] r46224 - in python/trunk: Lib/test/string_tests.py Objects/stringobject.c Objects/unicodeobject.c

fredrik.lundh python-checkins at python.org
Thu May 25 18:46:55 CEST 2006


Author: fredrik.lundh
Date: Thu May 25 18:46:54 2006
New Revision: 46224

Modified:
   python/trunk/Lib/test/string_tests.py
   python/trunk/Objects/stringobject.c
   python/trunk/Objects/unicodeobject.c
Log:
needforspeed: check for overflow in replace (from Andrew Dalke)



Modified: python/trunk/Lib/test/string_tests.py
==============================================================================
--- python/trunk/Lib/test/string_tests.py	(original)
+++ python/trunk/Lib/test/string_tests.py	Thu May 25 18:46:54 2006
@@ -555,15 +555,14 @@
         self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
         self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
 
-### Commented out until the underlying libraries are fixed
-##    def test_replace_overflow(self):
-##        # Check for overflow checking on 32 bit machines
-##        if sys.maxint != 2147483647:
-##            return
-##        A2_16 = "A" * (2**16)
-##        self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
-##        self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
-##        self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
+    def test_replace_overflow(self):
+        # Check for overflow checking on 32 bit machines
+        if sys.maxint != 2147483647:
+            return
+        A2_16 = "A" * (2**16)
+        self.checkraises(OverflowError, A2_16, "replace", "", A2_16)
+        self.checkraises(OverflowError, A2_16, "replace", "A", A2_16)
+        self.checkraises(OverflowError, A2_16, "replace", "AA", A2_16+A2_16)
 
     def test_zfill(self):
         self.checkequal('123', '123', 'zfill', 2)

Modified: python/trunk/Objects/stringobject.c
==============================================================================
--- python/trunk/Objects/stringobject.c	(original)
+++ python/trunk/Objects/stringobject.c	Thu May 25 18:46:54 2006
@@ -2460,6 +2460,7 @@
 	char *out_s;
 	char *new_s;
 	Py_ssize_t nfound, offset, new_len;
+        Py_ssize_t product, delta;
 
 	if (len == 0 || (pat_len == 0 && sub_len == 0) || pat_len > len)
 		goto return_same;
@@ -2473,7 +2474,24 @@
 	if (nfound == 0)
 		goto return_same;
 
-	new_len = len + nfound*(sub_len - pat_len);
+        delta = (sub_len - pat_len);
+        if (delta == 0) {
+            new_len = len;
+        } else {
+            product = nfound * (sub_len - pat_len);
+            if ((product / (sub_len - pat_len)) != nfound) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "replace string is too long");
+                return NULL;
+            }
+            new_len = len + product;
+            if (new_len < 0) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "replace string is too long");
+                return NULL;
+            }
+        }
+
 	if (new_len == 0) {
 		/* Have to allocate something for the caller to free(). */
 		out_s = (char *)PyMem_MALLOC(1);
@@ -2578,7 +2596,8 @@
 
 	new_s = mymemreplace(str,len,sub,sub_len,repl,repl_len,count,&out_len);
 	if (new_s == NULL) {
-		PyErr_NoMemory();
+		if (!PyErr_Occurred())
+			PyErr_NoMemory();
 		return NULL;
 	}
 	if (out_len == -1) {

Modified: python/trunk/Objects/unicodeobject.c
==============================================================================
--- python/trunk/Objects/unicodeobject.c	(original)
+++ python/trunk/Objects/unicodeobject.c	Thu May 25 18:46:54 2006
@@ -3866,9 +3866,11 @@
    for some more background, see: http://effbot.org/stringlib */
 
 /* note: fastsearch may access s[n], which isn't a problem when using
-   Python's ordinary string types.  also, the count mode returns -1 if
-   there cannot possible be a match in the target string, and 0 if it
-   has actually checked for matches. */
+   Python's ordinary string types, but may cause problems if you're
+   using this code in other contexts.  also, the count mode returns -1
+   if there cannot possible be a match in the target string, and 0 if
+   it has actually checked for matches, but didn't find any.  callers
+   beware! */
 
 #define FAST_COUNT 0
 #define FAST_SEARCH 1
@@ -4862,6 +4864,7 @@
     } else {
 
         Py_ssize_t n, i;
+        Py_ssize_t product, new_size, delta;
         Py_UNICODE *p;
 
         /* replace strings */
@@ -4870,7 +4873,25 @@
             n = maxcount;
         if (n == 0)
             goto nothing;
-        u = _PyUnicode_New(self->length + n * (str2->length - str1->length));
+        /* new_size = self->length + n * (str2->length - str1->length)); */
+        delta = (str2->length - str1->length);
+        if (delta == 0) {
+            new_size = self->length;
+        } else {
+            product = n * (str2->length - str1->length);
+            if ((product / (str2->length - str1->length)) != n) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "replace string is too long");
+                return NULL;
+            }
+            new_size = self->length + product;
+            if (new_size < 0) {
+                PyErr_SetString(PyExc_OverflowError,
+                                "replace string is too long");
+                return NULL;
+            }
+        }
+        u = _PyUnicode_New(new_size);
         if (!u)
             return NULL;
         i = 0;


More information about the Python-checkins mailing list