[pypy-commit] pypy default: Make the Python StringBuilder raise exceptions in the same place as the translated one, and get str.replace in Python raising the correct exception for overlfows on 32-bits again. Remove a duplicate test.

alex_gaynor noreply at buildbot.pypy.org
Mon Dec 19 21:50:47 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r50718:196c4e9bbd48
Date: 2011-12-19 20:50 +0000
http://bitbucket.org/pypy/pypy/changeset/196c4e9bbd48/

Log:	Make the Python StringBuilder raise exceptions in the same place as
	the translated one, and get str.replace in Python raising the
	correct exception for overlfows on 32-bits again. Remove a
	duplicate test.

diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -524,11 +524,16 @@
             upper = maxsplit - 1
             assert upper >= 0
         first = False
-        for i in range(upper):
+        try:
+            for i in range(upper):
+                builder.append(by)
+                builder.append(input[i])
             builder.append(by)
-            builder.append(input[i])
-        builder.append(by)
-        builder.append_slice(input, upper, len(input))
+            builder.append_slice(input, upper, len(input))
+        except MemoryError:
+            raise OperationError(space.w_OverflowError,
+                space.wrap("replace string too long")
+            )
     else:
         start = 0
         sublen = len(sub)
diff --git a/pypy/objspace/std/test/test_stringobject.py b/pypy/objspace/std/test/test_stringobject.py
--- a/pypy/objspace/std/test/test_stringobject.py
+++ b/pypy/objspace/std/test/test_stringobject.py
@@ -737,13 +737,6 @@
         iterable = "hello"
         raises(TypeError, len, iter(iterable))
 
-    def test_overflow_replace(self):
-        import sys
-        if sys.maxint > 2**31-1:
-            skip("Wrong platform")
-        x = "A" * (2**16)
-        raises(OverflowError, x.replace, '', x)
-
 class AppTestPrebuilt(AppTestStringObject):
     def setup_class(cls):
         cls.space = gettestobjspace(**{"objspace.std.withprebuiltchar": True})
diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -3,6 +3,7 @@
 
 from pypy.annotation.model import (SomeObject, SomeString, s_None, SomeChar,
     SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString, SomePtr, SomePBC)
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.tool.pairtype import pair, pairtype
 from pypy.rpython.extregistry import ExtRegistryEntry
 
@@ -52,25 +53,37 @@
 class AbstractStringBuilder(object):
     def __init__(self, init_size=INIT_SIZE):
         self.l = []
+        self.size = 0
+
+    def _grow(self, size):
+        try:
+            self.size = ovfcheck(self.size + size)
+        except OverflowError:
+            raise MemoryError
 
     def append(self, s):
         assert isinstance(s, self.tp)
         self.l.append(s)
+        self._grow(len(s))
 
     def append_slice(self, s, start, end):
         assert isinstance(s, self.tp)
         assert 0 <= start <= end <= len(s)
-        self.l.append(s[start:end])
+        s = s[start:end]
+        self.l.append(s)
+        self._grow(len(s))
 
     def append_multiple_char(self, c, times):
         assert isinstance(c, self.tp)
         self.l.append(c * times)
+        self._grow(times)
 
     def append_charpsize(self, s, size):
         l = []
         for i in xrange(size):
             l.append(s[i])
         self.l.append(self.tp("").join(l))
+        self._grow(size)
 
     def build(self):
         return self.tp("").join(self.l)


More information about the pypy-commit mailing list