]> granicus.if.org Git - python/commitdiff
Correct a crash when two successive unicode allocations fail with a MemoryError:
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Thu, 31 Jul 2008 23:39:05 +0000 (23:39 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Thu, 31 Jul 2008 23:39:05 +0000 (23:39 +0000)
the freelist contained half-initialized objects with freed pointers.

The comment
/* XXX UNREF/NEWREF interface should be more symmetrical */
was copied from tupleobject.c, and appears in some other places.
I sign the petition.

Lib/test/test_unicode.py
Objects/unicodeobject.c

index f82535317303439be78fa3e1231fab6ef0953bd4..b3d6907eacae70323d3e74732b063fc004fb8ff5 100644 (file)
@@ -1113,6 +1113,20 @@ class UnicodeTest(
         #  will fail
         self.assertRaises(UnicodeEncodeError, "foo{0}".format, u'\u1000bar')
 
+    def test_raiseMemError(self):
+        # Ensure that the freelist contains a consistent object, even
+        # when a string allocation fails with a MemoryError.
+        # This used to crash the interpreter,
+        # or leak references when the number was smaller.
+        try:
+            u"a" * (sys.maxint // 2 - 100)
+        except MemoryError:
+            pass
+        try:
+            u"a" * (sys.maxint // 2 - 100)
+        except MemoryError:
+            pass
+
 def test_main():
     test_support.run_unittest(__name__)
 
index 7abf984e66b9b21b74ffa9e92f34028873c35dc4..603c5070a8e384abf2758e78b1d6e2d4347a0d83 100644 (file)
@@ -315,7 +315,7 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
            if ((unicode->length < length) &&
                 unicode_resize(unicode, length) < 0) {
                PyObject_DEL(unicode->str);
-               goto onError;
+               unicode->str = NULL;
            }
        }
         else {
@@ -352,6 +352,8 @@ PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
     return unicode;
 
  onError:
+    /* XXX UNREF/NEWREF interface should be more symmetrical */
+    _Py_DEC_REFTOTAL;
     _Py_ForgetReference((PyObject *)unicode);
     PyObject_Del(unicode);
     return NULL;