Fix PyUnicode_Resize() for compact string: leave the string unchanged on error

Fix also PyUnicode_Resize() doc
This commit is contained in:
Victor Stinner 2011-12-12 13:08:33 +01:00
parent 521dfb02dd
commit b0a82a6a7f
2 changed files with 14 additions and 28 deletions

View File

@ -768,18 +768,15 @@ PyAPI_FUNC(int) PyUnicode_WriteChar(
PyAPI_FUNC(Py_UNICODE) PyUnicode_GetMax(void); PyAPI_FUNC(Py_UNICODE) PyUnicode_GetMax(void);
#endif #endif
/* Resize an Unicode object allocated by the legacy API (e.g. /* Resize an Unicode object. The length is the number of characters, except
PyUnicode_FromUnicode). Unicode objects allocated by the new API (e.g. if the kind of the string is PyUnicode_WCHAR_KIND: in this case, the length
PyUnicode_New) cannot be resized by this function. is the number of Py_UNICODE characters.
The length is a number of characters (and not the number of Py_UNICODE characters).
*unicode is modified to point to the new (resized) object and 0 *unicode is modified to point to the new (resized) object and 0
returned on success. returned on success.
If the refcount on the object is 1, the function resizes the string in Try to resize the string in place (which is usually faster than allocating
place, which is usually faster than allocating a new string (and copy a new string and copy characters), or create a new string.
characters).
Error handling is implemented as follows: an exception is set, -1 Error handling is implemented as follows: an exception is set, -1
is returned and *unicode left untouched. */ is returned and *unicode left untouched. */

View File

@ -655,7 +655,6 @@ resize_compact(PyObject *unicode, Py_ssize_t length)
share_wstr = _PyUnicode_SHARE_WSTR(unicode); share_wstr = _PyUnicode_SHARE_WSTR(unicode);
if (length > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) { if (length > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) {
Py_DECREF(unicode);
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
} }
@ -666,7 +665,7 @@ resize_compact(PyObject *unicode, Py_ssize_t length)
new_unicode = (PyObject *)PyObject_REALLOC((char *)unicode, new_size); new_unicode = (PyObject *)PyObject_REALLOC((char *)unicode, new_size);
if (new_unicode == NULL) { if (new_unicode == NULL) {
PyObject_Del(unicode); _Py_NewReference(unicode);
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return NULL;
} }
@ -834,8 +833,9 @@ _PyUnicode_New(Py_ssize_t length)
new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);
_PyUnicode_WSTR(unicode) = (Py_UNICODE*) PyObject_MALLOC(new_size); _PyUnicode_WSTR(unicode) = (Py_UNICODE*) PyObject_MALLOC(new_size);
if (!_PyUnicode_WSTR(unicode)) { if (!_PyUnicode_WSTR(unicode)) {
Py_DECREF(unicode);
PyErr_NoMemory(); PyErr_NoMemory();
goto onError; return NULL;
} }
/* Initialize the first element to guard against cases where /* Initialize the first element to guard against cases where
@ -860,13 +860,6 @@ _PyUnicode_New(Py_ssize_t length)
_PyUnicode_UTF8_LENGTH(unicode) = 0; _PyUnicode_UTF8_LENGTH(unicode) = 0;
assert(_PyUnicode_CheckConsistency((PyObject *)unicode, 0)); assert(_PyUnicode_CheckConsistency((PyObject *)unicode, 0));
return unicode; 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* static const char*
@ -1506,15 +1499,10 @@ unicode_dealloc(register PyObject *unicode)
PyObject_DEL(_PyUnicode_WSTR(unicode)); PyObject_DEL(_PyUnicode_WSTR(unicode));
if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) if (_PyUnicode_HAS_UTF8_MEMORY(unicode))
PyObject_DEL(_PyUnicode_UTF8(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);
Py_TYPE(unicode)->tp_free(unicode);
}
else {
if (_PyUnicode_DATA_ANY(unicode))
PyObject_DEL(_PyUnicode_DATA_ANY(unicode));
Py_TYPE(unicode)->tp_free(unicode);
}
} }
#ifdef Py_DEBUG #ifdef Py_DEBUG
@ -1590,9 +1578,10 @@ unicode_resize(PyObject **p_unicode, Py_ssize_t length)
} }
if (PyUnicode_IS_COMPACT(unicode)) { if (PyUnicode_IS_COMPACT(unicode)) {
*p_unicode = resize_compact(unicode, length); PyObject *new_unicode = resize_compact(unicode, length);
if (*p_unicode == NULL) if (new_unicode == NULL)
return -1; return -1;
*p_unicode = new_unicode;
assert(_PyUnicode_CheckConsistency(*p_unicode, 0)); assert(_PyUnicode_CheckConsistency(*p_unicode, 0));
return 0; return 0;
} }