Fix for SF bug 532646. This is a little simpler than what Neal

suggested there, based upon a better analysis (__getattr__ is a red
herring).  Will backport to 2.2.
This commit is contained in:
Guido van Rossum 2002-06-13 21:32:51 +00:00
parent 51290d369d
commit 16b93b3d0e
2 changed files with 31 additions and 1 deletions

View File

@ -274,3 +274,17 @@ class C2:
try: hash(C2())
except TypeError: pass
else: raise TestFailed, "hash(C2()) should raise an exception"
# Test for SF bug 532646
class A:
pass
A.__call__ = A()
a = A()
try:
a() # This should not segfault
except RuntimeError:
pass
else:
raise TestFailed, "how could this not have overflowed the stack?"

View File

@ -1879,6 +1879,7 @@ instance_iternext(PyInstanceObject *self)
static PyObject *
instance_call(PyObject *func, PyObject *arg, PyObject *kw)
{
PyThreadState *tstate = PyThreadState_GET();
PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
if (call == NULL) {
PyInstanceObject *inst = (PyInstanceObject*) func;
@ -1888,7 +1889,22 @@ instance_call(PyObject *func, PyObject *arg, PyObject *kw)
PyString_AsString(inst->in_class->cl_name));
return NULL;
}
res = PyObject_Call(call, arg, kw);
/* We must check and increment the recursion depth here. Scenario:
class A:
pass
A.__call__ = A() # that's right
a = A() # ok
a() # infinite recursion
This bounces between instance_call() and PyObject_Call() without
ever hitting eval_frame() (which has the main recursion check). */
if (tstate->recursion_depth++ > Py_GetRecursionLimit()) {
PyErr_SetString(PyExc_RuntimeError,
"maximum __call__ recursion depth exceeded");
res = NULL;
}
else
res = PyObject_Call(call, arg, kw);
tstate->recursion_depth--;
Py_DECREF(call);
return res;
}