[Python-checkins] cpython: Fix PyUnicode_Resize() for compact string: leave the string unchanged on error

victor.stinner python-checkins at python.org
Mon Dec 12 13:09:06 CET 2011


http://hg.python.org/cpython/rev/61a2cae5308c
changeset:   73946:61a2cae5308c
user:        Victor Stinner <victor.stinner at haypocalc.com>
date:        Mon Dec 12 13:08:33 2011 +0100
summary:
  Fix PyUnicode_Resize() for compact string: leave the string unchanged on error

Fix also PyUnicode_Resize() doc

files:
  Include/unicodeobject.h |  13 ++++-------
  Objects/unicodeobject.c |  31 +++++++++-------------------
  2 files changed, 15 insertions(+), 29 deletions(-)


diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h
--- a/Include/unicodeobject.h
+++ b/Include/unicodeobject.h
@@ -768,18 +768,15 @@
 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
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -655,7 +655,6 @@
     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 @@
 
     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 @@
     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_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 @@
         PyObject_DEL(_PyUnicode_WSTR(unicode));
     if (_PyUnicode_HAS_UTF8_MEMORY(unicode))
         PyObject_DEL(_PyUnicode_UTF8(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);
-    }
+    if (!PyUnicode_IS_COMPACT(unicode) && _PyUnicode_DATA_ANY(unicode))
+        PyObject_DEL(_PyUnicode_DATA_ANY(unicode));
+
+    Py_TYPE(unicode)->tp_free(unicode);
 }
 
 #ifdef Py_DEBUG
@@ -1590,9 +1578,10 @@
     }
 
     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;
     }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list