mirror of
https://github.com/python/cpython.git
synced 2025-11-25 12:44:13 +00:00
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).
This commit is contained in:
parent
208eec2cad
commit
0edc7a03e2
3 changed files with 36 additions and 8 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import unittest
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
from test import test_support
|
from test import test_support
|
||||||
|
|
||||||
|
|
@ -175,6 +176,25 @@ class TestReversed(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, reversed)
|
self.assertRaises(TypeError, reversed)
|
||||||
self.assertRaises(TypeError, reversed, [], 'extra')
|
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):
|
def test_main(verbose=None):
|
||||||
testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig,
|
testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig,
|
||||||
TestReversed)
|
TestReversed)
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ What's New in Python 2.5 alpha 1?
|
||||||
Core and builtins
|
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
|
- SF bug #1185883: Python's small-object memory allocator took over
|
||||||
a block managed by the platform C library whenever a realloc specified
|
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
|
a small new size. However, there's no portable way to know then how
|
||||||
|
|
|
||||||
|
|
@ -1797,7 +1797,9 @@ PyObject *
|
||||||
PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
|
PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
|
||||||
{
|
{
|
||||||
va_list va;
|
va_list va;
|
||||||
PyObject *args, *func = 0, *retval;
|
PyObject *args = NULL;
|
||||||
|
PyObject *func = NULL;
|
||||||
|
PyObject *retval = NULL;
|
||||||
|
|
||||||
if (o == NULL || name == NULL)
|
if (o == NULL || name == NULL)
|
||||||
return null_error();
|
return null_error();
|
||||||
|
|
@ -1808,8 +1810,10 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyCallable_Check(func))
|
if (!PyCallable_Check(func)) {
|
||||||
return type_error("call of non-callable attribute");
|
type_error("call of non-callable attribute");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (format && *format) {
|
if (format && *format) {
|
||||||
va_start(va, format);
|
va_start(va, format);
|
||||||
|
|
@ -1820,23 +1824,24 @@ PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
|
||||||
args = PyTuple_New(0);
|
args = PyTuple_New(0);
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
return NULL;
|
goto exit;
|
||||||
|
|
||||||
if (!PyTuple_Check(args)) {
|
if (!PyTuple_Check(args)) {
|
||||||
PyObject *a;
|
PyObject *a;
|
||||||
|
|
||||||
a = PyTuple_New(1);
|
a = PyTuple_New(1);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
return NULL;
|
goto exit;
|
||||||
if (PyTuple_SetItem(a, 0, args) < 0)
|
if (PyTuple_SetItem(a, 0, args) < 0)
|
||||||
return NULL;
|
goto exit;
|
||||||
args = a;
|
args = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = PyObject_Call(func, args, NULL);
|
retval = PyObject_Call(func, args, NULL);
|
||||||
|
|
||||||
Py_DECREF(args);
|
exit:
|
||||||
Py_DECREF(func);
|
Py_XDECREF(args);
|
||||||
|
Py_XDECREF(func);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue