From b0a82a6a7f0686f99e19cc04b498abcd2896b906 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 12 Dec 2011 13:08:33 +0100 Subject: Fix PyUnicode_Resize() for compact string: leave the string unchanged on error Fix also PyUnicode_Resize() doc --- Include/unicodeobject.h | 13 +++++-------- Objects/unicodeobject.c | 29 +++++++++-------------------- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index 235c677..32d7df7 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -768,18 +768,15 @@ PyAPI_FUNC(int) PyUnicode_WriteChar( PyAPI_FUNC(Py_UNICODE) PyUnicode_GetMax(void); #endif -/* Resize an Unicode object allocated by the legacy API (e.g. - PyUnicode_FromUnicode). Unicode objects allocated by the new API (e.g. - PyUnicode_New) cannot be resized by this function. - - The length is a number of characters (and not the number of Py_UNICODE characters). +/* Resize an Unicode object. The length is the number of characters, except + if the kind of the string is PyUnicode_WCHAR_KIND: in this case, the length + is the number of Py_UNICODE characters. *unicode is modified to point to the new (resized) object and 0 returned on success. - If the refcount on the object is 1, the function resizes the string in - place, which is usually faster than allocating a new string (and copy - characters). + Try to resize the string in place (which is usually faster than allocating + a new string and copy characters), or create a new string. Error handling is implemented as follows: an exception is set, -1 is returned and *unicode left untouched. */ diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5c2d2a7..6edba5d 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -655,7 +655,6 @@ resize_compact(PyObject *unicode, Py_ssize_t length) share_wstr = _PyUnicode_SHARE_WSTR(unicode); if (length > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) { - Py_DECREF(unicode); PyErr_NoMemory(); return NULL; } @@ -666,7 +665,7 @@ resize_compact(PyObject *unicode, Py_ssize_t length) new_unicode = (PyObject *)PyObject_REALLOC((char *)unicode, new_size); if (new_unicode == NULL) { - PyObject_Del(unicode); + _Py_NewReference(unicode); PyErr_NoMemory(); return NULL; } @@ -834,8 +833,9 @@ _PyUnicode_New(Py_ssize_t length) new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); _PyUnicode_WSTR(unicode) = (Py_UNICODE*) PyObject_MALLOC(new_size); if (!_PyUnicode_WSTR(unicode)) { + Py_DECREF(unicode); PyErr_NoMemory(); - goto onError; + return NULL; } /* Initialize the first element to guard against cases where @@ -860,13 +860,6 @@ _PyUnicode_New(Py_ssize_t length) _PyUnicode_UTF8_LENGTH(unicode) = 0; assert(_PyUnicode_CheckConsistency((PyObject *)unicode, 0)); return unicode; - - onError: - /* XXX UNREF/NEWREF interface should be more symmetrical */ - _Py_DEC_REFTOTAL; - _Py_ForgetReference((PyObject *)unicode); - PyObject_Del(unicode); - return NULL; } static const char* @@ -1506,15 +1499,10 @@ unicode_dealloc(register PyObject *unicode) PyObject_DEL(_PyUnicode_WSTR(unicode)); if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) PyObject_DEL(_PyUnicode_UTF8(unicode)); + if (!PyUnicode_IS_COMPACT(unicode) && _PyUnicode_DATA_ANY(unicode)) + PyObject_DEL(_PyUnicode_DATA_ANY(unicode)); - if (PyUnicode_IS_COMPACT(unicode)) { - Py_TYPE(unicode)->tp_free(unicode); - } - else { - if (_PyUnicode_DATA_ANY(unicode)) - PyObject_DEL(_PyUnicode_DATA_ANY(unicode)); - Py_TYPE(unicode)->tp_free(unicode); - } + Py_TYPE(unicode)->tp_free(unicode); } #ifdef Py_DEBUG @@ -1590,9 +1578,10 @@ unicode_resize(PyObject **p_unicode, Py_ssize_t length) } if (PyUnicode_IS_COMPACT(unicode)) { - *p_unicode = resize_compact(unicode, length); - if (*p_unicode == NULL) + PyObject *new_unicode = resize_compact(unicode, length); + if (new_unicode == NULL) return -1; + *p_unicode = new_unicode; assert(_PyUnicode_CheckConsistency(*p_unicode, 0)); return 0; } -- cgit v0.12