Index: Lib/ctypes/test/test_as_parameter.py =================================================================== --- Lib/ctypes/test/test_as_parameter.py (revision 84911) +++ Lib/ctypes/test/test_as_parameter.py (working copy) @@ -187,6 +187,18 @@ self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h), (9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9)) + def test_recursive_as_param(self): + from ctypes import c_int + + class A(object): + pass + + a = A() + a._as_parameter_ = a + with self.assertRaises(RuntimeError): + c_int.from_param(a) + + #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class AsParamWrapper(object): Index: Modules/_ctypes/_ctypes.c =================================================================== --- Modules/_ctypes/_ctypes.c (revision 84911) +++ Modules/_ctypes/_ctypes.c (working copy) @@ -2053,12 +2053,9 @@ return (PyObject *)result; } -/* - * This is a *class method*. - * Convert a parameter into something that ConvParam can handle. - */ -static PyObject * -PyCSimpleType_from_param(PyObject *type, PyObject *value) + +static PyObject* +internal_csimpletype_from_param(PyObject *type, PyObject *value, PyObject *seen) { StgDictObject *dict; char *fmt; @@ -2097,7 +2094,17 @@ as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); if (as_parameter) { - value = PyCSimpleType_from_param(type, as_parameter); + if (PySet_Contains(seen, as_parameter)) { + PyErr_Format(PyExc_RuntimeError, + "_as_parameter_ contains recursive data" + ); + return NULL; + } + + if (PySet_Add(seen, as_parameter)) { + return NULL; + } + value = internal_csimpletype_from_param(type, as_parameter, seen); Py_DECREF(as_parameter); return value; } @@ -2105,6 +2112,18 @@ "wrong type"); return NULL; } +/* + * This is a *class method*. + * Convert a parameter into something that ConvParam can handle. + */ +static PyObject * +PyCSimpleType_from_param(PyObject *type, PyObject *value) +{ + PyObject *seen = PySet_New(NULL); + PyObject *result = internal_csimpletype_from_param(type, value, seen); + Py_DECREF(seen); + return result; +} static PyMethodDef PyCSimpleType_methods[] = { { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc },