diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py index f82535317303..b3d6907eacae 100644 --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1113,6 +1113,20 @@ def __format__(self, format_spec): # 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__) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 7abf984e66b9..603c5070a8e3 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -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;