From 71436f022996b82b2e2518ee5dd08d1a2923eaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDiga=20Seilnacht?= Date: Wed, 14 Mar 2007 12:24:09 +0000 Subject: 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. Will backport. --- Lib/test/test_descr.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ 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 7e2313d..71f4ec4 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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 diff --git a/Misc/NEWS b/Misc/NEWS index be9e972..56b9007 100644 --- 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 diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 020a9bb..dbb9ada 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -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++) { -- cgit v0.12