import unittest
from test import test_support
+import sys
\f
self.assertEqual(True, issubclass(int, (long, (float, int))))
self.assertEqual(True, issubclass(str, (unicode, (Child, NewChild, basestring))))
-
+ def test_subclass_recursion_limit(self):
+ # make sure that issubclass raises RuntimeError before the C stack is
+ # blown
+ self.assertRaises(RuntimeError, blowstack, issubclass, str, str)
+
+ def test_isinstance_recursion_limit(self):
+ # make sure that issubclass raises RuntimeError before the C stack is
+ # blown
+ self.assertRaises(RuntimeError, blowstack, isinstance, '', str)
+
+def blowstack(fxn, arg, compare_to):
+ # Make sure that calling isinstance with a deeply nested tuple for its
+ # argument will raise RuntimeError eventually.
+ tuple_arg = (compare_to,)
+ for cnt in xrange(sys.getrecursionlimit()+5):
+ tuple_arg = (tuple_arg,)
+ fxn(arg, tuple_arg)
\f
def test_main():
return -1;
}
-int
-PyObject_IsInstance(PyObject *inst, PyObject *cls)
+static int
+recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth)
{
PyObject *icls;
static PyObject *__class__ = NULL;
}
}
else if (PyTuple_Check(cls)) {
- /* Not a general sequence -- that opens up the road to
- recursion and stack overflow. */
int i, n;
+ if (!recursion_depth) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "nest level of tuple too deep");
+ return NULL;
+ }
+
n = PyTuple_GET_SIZE(cls);
for (i = 0; i < n; i++) {
- retval = PyObject_IsInstance(
- inst, PyTuple_GET_ITEM(cls, i));
+ retval = recursive_isinstance(
+ inst,
+ PyTuple_GET_ITEM(cls, i),
+ recursion_depth-1);
if (retval != 0)
break;
}
}
int
-PyObject_IsSubclass(PyObject *derived, PyObject *cls)
+PyObject_IsInstance(PyObject *inst, PyObject *cls)
+{
+ return recursive_isinstance(inst, cls, Py_GetRecursionLimit());
+}
+
+static int
+recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth)
{
int retval;
if (PyTuple_Check(cls)) {
int i;
int n = PyTuple_GET_SIZE(cls);
+
+ if (!recursion_depth) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "nest level of tuple too deep");
+ return NULL;
+ }
for (i = 0; i < n; ++i) {
- retval = PyObject_IsSubclass(
- derived, PyTuple_GET_ITEM(cls, i));
+ retval = recursive_issubclass(
+ derived,
+ PyTuple_GET_ITEM(cls, i),
+ recursion_depth-1);
if (retval != 0) {
/* either found it, or got an error */
return retval;
return retval;
}
+int
+PyObject_IsSubclass(PyObject *derived, PyObject *cls)
+{
+ return recursive_issubclass(derived, cls, Py_GetRecursionLimit());
+}
+
+
PyObject *
PyObject_GetIter(PyObject *o)
{