From 0edc7a03e2505c4e9b3186f8b6caa18a7b3988e2 Mon Sep 17 00:00:00 2001 From: "Michael W. Hudson" Date: Tue, 12 Jul 2005 10:21:19 +0000 Subject: 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). --- Lib/test/test_enumerate.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 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) diff --git a/Misc/NEWS b/Misc/NEWS index 4f41ab1..13c7761 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -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; } -- cgit v0.12