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);
#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. */

View File

@ -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;
}