diff options
author | Žiga Seilnacht <ziga.seilnacht@gmail.com> | 2007-03-14 12:34:30 +0000 |
---|---|---|
committer | Žiga Seilnacht <ziga.seilnacht@gmail.com> | 2007-03-14 12:34:30 +0000 |
commit | 94c887258c252fe4699b490b9b43185b0769c080 (patch) | |
tree | d88dbe4b5c85e9b0727dec2c7d2c2b03cccc56f2 | |
parent | 027ac24650f0cb48d0391ce34749ddfb29419f57 (diff) | |
download | cpython-git-94c887258c252fe4699b490b9b43185b0769c080.tar.gz |
Patch #1680015: Don't modify __slots__ tuple if it contains an unicode
name. Remove a reference leak that happened if the name could not be
converted to string.
(backport from rev. 54378)
-rw-r--r-- | Lib/test/test_descr.py | 23 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Objects/typeobject.c | 36 |
3 files changed, 46 insertions, 16 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 0981f09524..a29f404f5f 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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 @@ -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). diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 4f2740230d..4a58a8619e 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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++) { |