]> granicus.if.org Git - python/commitdiff
Patch #1680015: Don't modify __slots__ tuple if it contains an unicode
authorŽiga Seilnacht <ziga.seilnacht@gmail.com>
Wed, 14 Mar 2007 12:34:30 +0000 (12:34 +0000)
committerŽiga Seilnacht <ziga.seilnacht@gmail.com>
Wed, 14 Mar 2007 12:34:30 +0000 (12:34 +0000)
name. Remove a reference leak that happened if the name could not be
converted to string.
 (backport from rev. 54378)

Lib/test/test_descr.py
Misc/NEWS
Objects/typeobject.c

index 0981f095246fbd57d20ebf11556c7cef81f5cc10..a29f404f5f2d83c7c77e39bbeade7a71f661dec6 100644 (file)
@@ -1210,6 +1210,29 @@ def slots():
     class C(object):
         __slots__ = ["a", "a_b", "_a", "A0123456789Z"]
 
+    # Test unicode slot names
+    try:
+        unichr
+    except NameError:
+        pass
+    else:
+        # _unicode_to_string used to modify slots in certain circumstances 
+        slots = (unicode("foo"), unicode("bar"))
+        class C(object):
+            __slots__ = slots
+        x = C()
+        x.foo = 5
+        vereq(x.foo, 5)
+        veris(type(slots[0]), unicode)
+        # this used to leak references
+        try:
+            class C(object):
+                __slots__ = [unichr(128)]
+        except (TypeError, UnicodeEncodeError):
+            pass
+        else:
+            raise TestFailed, "[unichr(128)] slots not caught" 
+
     # Test leaks
     class Counted(object):
         counter = 0    # counts the number of instances alive
index 379899444e26451490c4c2374c6c688bcd047bc8..362e326291623fb138252dc08c269083be664382 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5.1c1?
 Core and builtins
 -----------------
 
+- Patch #1680015: Don't modify __slots__ tuple if it contains an unicode
+  name.
+
 - Patch #922167: Python no longer segfaults when faced with infinitely
   self-recursive reload() calls (as reported by bug #742342).
 
index 4f2740230dd9327b50e68471461cc614183abe73..4a58a8619eb0d1999088e6e50de00b4f410aeb0a 100644 (file)
@@ -1573,29 +1573,33 @@ valid_identifier(PyObject *s)
 static PyObject *
 _unicode_to_string(PyObject *slots, Py_ssize_t nslots)
 {
-       PyObject *tmp = slots;
-       PyObject *o, *o1;
+       PyObject *tmp = NULL;
+       PyObject *slot_name, *new_name;
        Py_ssize_t i;
-       ssizessizeargfunc copy = slots->ob_type->tp_as_sequence->sq_slice;
+
        for (i = 0; i < nslots; i++) {
-               if (PyUnicode_Check(o = PyTuple_GET_ITEM(tmp, i))) {
-                       if (tmp == slots) {
-                               tmp = copy(slots, 0, PyTuple_GET_SIZE(slots));
+               if (PyUnicode_Check(slot_name = PyTuple_GET_ITEM(slots, i))) {
+                       if (tmp == NULL) {
+                               tmp = PySequence_List(slots);
                                if (tmp == NULL)
                                        return NULL;
                        }
-                       o1 = _PyUnicode_AsDefaultEncodedString
-                                       (o, NULL);
-                       if (o1 == NULL) {
+                       new_name = _PyUnicode_AsDefaultEncodedString(slot_name,
+                                                                    NULL);
+                       if (new_name == NULL) {
                                Py_DECREF(tmp);
-                               return 0;
+                               return NULL;
                        }
-                       Py_INCREF(o1);
-                       Py_DECREF(o);
-                       PyTuple_SET_ITEM(tmp, i, o1);
+                       Py_INCREF(new_name);
+                       PyList_SET_ITEM(tmp, i, new_name);
+                       Py_DECREF(slot_name);
                }
        }
-       return tmp;
+       if (tmp != NULL) {
+               slots = PyList_AsTuple(tmp);
+               Py_DECREF(tmp);
+       }
+       return slots;
 }
 #endif
 
@@ -1742,12 +1746,12 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
 
 #ifdef Py_USING_UNICODE
                tmp = _unicode_to_string(slots, nslots);
+               if (tmp == NULL)
+                       goto bad_slots;
                if (tmp != slots) {
                        Py_DECREF(slots);
                        slots = tmp;
                }
-               if (!tmp)
-                       return NULL;
 #endif
                /* Check for valid slot names and two special cases */
                for (i = 0; i < nslots; i++) {