]> 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:24:09 +0000 (12:24 +0000)
committerŽiga Seilnacht <ziga.seilnacht@gmail.com>
Wed, 14 Mar 2007 12:24:09 +0000 (12:24 +0000)
name. Remove a reference leak that happened if the name could not be
converted to string. Will backport.

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

index 7e2313da182451dbaa9b3a38e342abf9010c67e9..71f4ec43cd5ba8c834a5dfeecffaba49c21aea2e 100644 (file)
@@ -1226,6 +1226,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 be9e972ae81b9bae5eead5107577de94795074ca..56b9007c8ef93256049b547a03c907779ca96269 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1?
 Core and builtins
 -----------------
 
+- Patch #1680015: Don't modify __slots__ tuple if it contains an unicode
+  name.
+
 - Patch #1444529: the builtin compile() now accepts keyword arguments.
 
 - Bug #1678647: write a newline after printing an exception in any
index 020a9bb646a47a0f2f85debe99fc17449404bf2d..dbb9ada5eb6ead335192bfc6daf20a78f09b02c2 100644 (file)
@@ -1654,29 +1654,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
 
@@ -1804,12 +1808,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++) {