summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael W. Hudson <mwh@python.net>2005-07-12 10:21:19 (GMT)
committerMichael W. Hudson <mwh@python.net>2005-07-12 10:21:19 (GMT)
commit0edc7a03e2505c4e9b3186f8b6caa18a7b3988e2 (patch)
treec192e6bf89c8bcbcdd869a01bbec4cc3981a1f6a
parent208eec2cad5dcfdd7fe2c8fa706ec5e89533c87d (diff)
downloadcpython-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.py20
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/abstract.c21
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;
}