diff options
author | Michael W. Hudson <mwh@python.net> | 2005-07-12 10:21:19 (GMT) |
---|---|---|
committer | Michael W. Hudson <mwh@python.net> | 2005-07-12 10:21:19 (GMT) |
commit | 0edc7a03e2505c4e9b3186f8b6caa18a7b3988e2 (patch) | |
tree | c192e6bf89c8bcbcdd869a01bbec4cc3981a1f6a | |
parent | 208eec2cad5dcfdd7fe2c8fa706ec5e89533c87d (diff) | |
download | cpython-0edc7a03e2505c4e9b3186f8b6caa18a7b3988e2.zip cpython-0edc7a03e2505c4e9b3186f8b6caa18a7b3988e2.tar.gz cpython-0edc7a03e2505c4e9b3186f8b6caa18a7b3988e2.tar.bz2 |
Fix:
[ 1229429 ] missing Py_DECREF in PyObject_CallMethod
Add a test in test_enumerate, which is a bit random, but suffices
(reversed_new calls PyObject_CallMethod under some circumstances).
-rw-r--r-- | Lib/test/test_enumerate.py | 20 | ||||
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Objects/abstract.c | 21 |
3 files changed, 36 insertions, 8 deletions
diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py index 0ed2b4c..0a88e8d 100644 --- a/Lib/test/test_enumerate.py +++ b/Lib/test/test_enumerate.py @@ -1,4 +1,5 @@ import unittest +import sys from test import test_support @@ -175,6 +176,25 @@ class TestReversed(unittest.TestCase): self.assertRaises(TypeError, reversed) self.assertRaises(TypeError, reversed, [], 'extra') + def test_bug1229429(self): + # this bug was never in reversed, it was in + # PyObject_CallMethod, and reversed_new calls that sometimes. + if not hasattr(sys, "getrefcount"): + return + def f(): + pass + r = f.__reversed__ = object() + rc = sys.getrefcount(r) + for i in range(10): + try: + reversed(f) + except TypeError: + pass + else: + self.fail("non-callable __reversed__ didn't raise!") + self.assertEqual(rc, sys.getrefcount(r)) + + def test_main(verbose=None): testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig, TestReversed) @@ -12,6 +12,9 @@ What's New in Python 2.5 alpha 1? Core and builtins ----------------- +- SF bug #1229429: PyObject_CallMethod failed to decrement some + reference counts in some error exit cases. + - SF bug #1185883: Python's small-object memory allocator took over a block managed by the platform C library whenever a realloc specified a small new size. However, there's no portable way to know then how diff --git a/Objects/abstract.c b/Objects/abstract.c index d28006a..cade2aa 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1797,7 +1797,9 @@ PyObject * PyObject_CallMethod(PyObject *o, char *name, char *format, ...) { va_list va; - PyObject *args, *func = 0, *retval; + PyObject *args = NULL; + PyObject *func = NULL; + PyObject *retval = NULL; if (o == NULL || name == NULL) return null_error(); @@ -1808,8 +1810,10 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...) return 0; } - if (!PyCallable_Check(func)) - return type_error("call of non-callable attribute"); + if (!PyCallable_Check(func)) { + type_error("call of non-callable attribute"); + goto exit; + } if (format && *format) { va_start(va, format); @@ -1820,23 +1824,24 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...) args = PyTuple_New(0); if (!args) - return NULL; + goto exit; if (!PyTuple_Check(args)) { PyObject *a; a = PyTuple_New(1); if (a == NULL) - return NULL; + goto exit; if (PyTuple_SetItem(a, 0, args) < 0) - return NULL; + goto exit; args = a; } retval = PyObject_Call(func, args, NULL); - Py_DECREF(args); - Py_DECREF(func); + exit: + Py_XDECREF(args); + Py_XDECREF(func); return retval; } |