Skip to content

Commit b0a82a6

Browse files
author
Victor Stinner
committed
Fix PyUnicode_Resize() for compact string: leave the string unchanged on error
Fix also PyUnicode_Resize() doc
1 parent 521dfb0 commit b0a82a6

File tree

2 files changed

+14
-28
lines changed

2 files changed

+14
-28
lines changed

Include/unicodeobject.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -768,18 +768,15 @@ PyAPI_FUNC(int) PyUnicode_WriteChar(
768768
PyAPI_FUNC(Py_UNICODE) PyUnicode_GetMax(void);
769769
#endif
770770

771-
/* Resize an Unicode object allocated by the legacy API (e.g.
772-
PyUnicode_FromUnicode). Unicode objects allocated by the new API (e.g.
773-
PyUnicode_New) cannot be resized by this function.
774-
775-
The length is a number of characters (and not the number of Py_UNICODE characters).
771+
/* Resize an Unicode object. The length is the number of characters, except
772+
if the kind of the string is PyUnicode_WCHAR_KIND: in this case, the length
773+
is the number of Py_UNICODE characters.
776774
777775
*unicode is modified to point to the new (resized) object and 0
778776
returned on success.
779777
780-
If the refcount on the object is 1, the function resizes the string in
781-
place, which is usually faster than allocating a new string (and copy
782-
characters).
778+
Try to resize the string in place (which is usually faster than allocating
779+
a new string and copy characters), or create a new string.
783780
784781
Error handling is implemented as follows: an exception is set, -1
785782
is returned and *unicode left untouched. */

Objects/unicodeobject.c

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,6 @@ resize_compact(PyObject *unicode, Py_ssize_t length)
655655
share_wstr = _PyUnicode_SHARE_WSTR(unicode);
656656

657657
if (length > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) {
658-
Py_DECREF(unicode);
659658
PyErr_NoMemory();
660659
return NULL;
661660
}
@@ -666,7 +665,7 @@ resize_compact(PyObject *unicode, Py_ssize_t length)
666665

667666
new_unicode = (PyObject *)PyObject_REALLOC((char *)unicode, new_size);
668667
if (new_unicode == NULL) {
669-
PyObject_Del(unicode);
668+
_Py_NewReference(unicode);
670669
PyErr_NoMemory();
671670
return NULL;
672671
}
@@ -834,8 +833,9 @@ _PyUnicode_New(Py_ssize_t length)
834833
new_size = sizeof(Py_UNICODE) * ((size_t)length + 1);
835834
_PyUnicode_WSTR(unicode) = (Py_UNICODE*) PyObject_MALLOC(new_size);
836835
if (!_PyUnicode_WSTR(unicode)) {
836+
Py_DECREF(unicode);
837837
PyErr_NoMemory();
838-
goto onError;
838+
return NULL;
839839
}
840840

841841
/* Initialize the first element to guard against cases where
@@ -860,13 +860,6 @@ _PyUnicode_New(Py_ssize_t length)
860860
_PyUnicode_UTF8_LENGTH(unicode) = 0;
861861
assert(_PyUnicode_CheckConsistency((PyObject *)unicode, 0));
862862
return unicode;
863-
864-
onError:
865-
/* XXX UNREF/NEWREF interface should be more symmetrical */
866-
_Py_DEC_REFTOTAL;
867-
_Py_ForgetReference((PyObject *)unicode);
868-
PyObject_Del(unicode);
869-
return NULL;
870863
}
871864

872865
static const char*
@@ -1506,15 +1499,10 @@ unicode_dealloc(register PyObject *unicode)
15061499
PyObject_DEL(_PyUnicode_WSTR(unicode));
15071500
if (_PyUnicode_HAS_UTF8_MEMORY(unicode))
15081501
PyObject_DEL(_PyUnicode_UTF8(unicode));
1502+
if (!PyUnicode_IS_COMPACT(unicode) && _PyUnicode_DATA_ANY(unicode))
1503+
PyObject_DEL(_PyUnicode_DATA_ANY(unicode));
15091504

1510-
if (PyUnicode_IS_COMPACT(unicode)) {
1511-
Py_TYPE(unicode)->tp_free(unicode);
1512-
}
1513-
else {
1514-
if (_PyUnicode_DATA_ANY(unicode))
1515-
PyObject_DEL(_PyUnicode_DATA_ANY(unicode));
1516-
Py_TYPE(unicode)->tp_free(unicode);
1517-
}
1505+
Py_TYPE(unicode)->tp_free(unicode);
15181506
}
15191507

15201508
#ifdef Py_DEBUG
@@ -1590,9 +1578,10 @@ unicode_resize(PyObject **p_unicode, Py_ssize_t length)
15901578
}
15911579

15921580
if (PyUnicode_IS_COMPACT(unicode)) {
1593-
*p_unicode = resize_compact(unicode, length);
1594-
if (*p_unicode == NULL)
1581+
PyObject *new_unicode = resize_compact(unicode, length);
1582+
if (new_unicode == NULL)
15951583
return -1;
1584+
*p_unicode = new_unicode;
15961585
assert(_PyUnicode_CheckConsistency(*p_unicode, 0));
15971586
return 0;
15981587
}

0 commit comments

Comments
 (0)