diff options
author | Benjamin Peterson <benjamin@python.org> | 2011-03-26 23:18:09 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2011-03-26 23:18:09 (GMT) |
commit | eb2389be0e00551d42ddd5eaa89adef8eb48c8dd (patch) | |
tree | 54a10b5b56a1aa1d40aeb823a38e57015541951f | |
parent | b04d70d993d3aec544a8dc552ca1b36e3fae730c (diff) | |
parent | 1a07f07337dc722b9d6f347944abca4c8fbf5f02 (diff) | |
download | cpython-eb2389be0e00551d42ddd5eaa89adef8eb48c8dd.zip cpython-eb2389be0e00551d42ddd5eaa89adef8eb48c8dd.tar.gz cpython-eb2389be0e00551d42ddd5eaa89adef8eb48c8dd.tar.bz2 |
merge 3.2
-rw-r--r-- | Lib/ctypes/test/test_as_parameter.py | 12 | ||||
-rw-r--r-- | Misc/NEWS | 6 | ||||
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 74 |
3 files changed, 72 insertions, 20 deletions
diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py index 835398f..475d595 100644 --- a/Lib/ctypes/test/test_as_parameter.py +++ b/Lib/ctypes/test/test_as_parameter.py @@ -187,6 +187,18 @@ class BasicWrapTestCase(unittest.TestCase): 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): @@ -322,6 +322,12 @@ Tools/Demos - Issue #11179: Make ccbench work under Python 3.1 and 2.7 again. +Extensions +---------- + +- Issue #1838: Prevent segfault in ctypes, when _as_parameter_ on a class is set + to an instance of the class. + Tests ----- diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index c593b32..79c8663 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -585,7 +585,10 @@ static PyObject * CDataType_from_param(PyObject *type, PyObject *value) { PyObject *as_parameter; - if (1 == PyObject_IsInstance(value, type)) { + int res = PyObject_IsInstance(value, type); + if (res == -1) + return NULL; + if (res) { Py_INCREF(value); return value; } @@ -598,10 +601,14 @@ CDataType_from_param(PyObject *type, PyObject *value) /* If we got a PyCArgObject, we must check if the object packed in it is an instance of the type's dict->proto */ - if(dict && ob - && PyObject_IsInstance(ob, dict->proto)) { - Py_INCREF(value); - return value; + if(dict && ob) { + res = PyObject_IsInstance(ob, dict->proto); + if (res == -1) + return NULL; + if (res) { + Py_INCREF(value); + return value; + } } ob_name = (ob) ? Py_TYPE(ob)->tp_name : "???"; PyErr_Format(PyExc_TypeError, @@ -951,8 +958,7 @@ PyCPointerType_from_param(PyObject *type, PyObject *value) Py_INCREF(value); /* _byref steals a refcount */ return _byref(value); case -1: - PyErr_Clear(); - break; + return NULL; default: break; } @@ -1431,6 +1437,7 @@ static PyObject * c_wchar_p_from_param(PyObject *type, PyObject *value) { PyObject *as_parameter; + int res; if (value == Py_None) { Py_INCREF(Py_None); return Py_None; @@ -1451,7 +1458,10 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) } return (PyObject *)parg; } - if (PyObject_IsInstance(value, type)) { + res = PyObject_IsInstance(value, type); + if (res == -1) + return NULL; + if (res) { Py_INCREF(value); return value; } @@ -1492,6 +1502,7 @@ static PyObject * c_char_p_from_param(PyObject *type, PyObject *value) { PyObject *as_parameter; + int res; if (value == Py_None) { Py_INCREF(Py_None); return Py_None; @@ -1512,7 +1523,10 @@ c_char_p_from_param(PyObject *type, PyObject *value) } return (PyObject *)parg; } - if (PyObject_IsInstance(value, type)) { + res = PyObject_IsInstance(value, type); + if (res == -1) + return NULL; + if (res) { Py_INCREF(value); return value; } @@ -1554,6 +1568,7 @@ c_void_p_from_param(PyObject *type, PyObject *value) { StgDictObject *stgd; PyObject *as_parameter; + int res; /* None */ if (value == Py_None) { @@ -1631,7 +1646,10 @@ c_void_p_from_param(PyObject *type, PyObject *value) return (PyObject *)parg; } /* c_void_p instance (or subclass) */ - if (PyObject_IsInstance(value, type)) { + res = PyObject_IsInstance(value, type); + if (res == -1) + return NULL; + if (res) { /* c_void_p instances */ Py_INCREF(value); return value; @@ -1990,10 +2008,14 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) PyCArgObject *parg; struct fielddesc *fd; PyObject *as_parameter; + int res; /* If the value is already an instance of the requested type, we can use it as is */ - if (1 == PyObject_IsInstance(value, type)) { + res = PyObject_IsInstance(value, type); + if (res == -1) + return NULL; + if (res) { Py_INCREF(value); return value; } @@ -2022,7 +2044,12 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) as_parameter = PyObject_GetAttrString(value, "_as_parameter_"); if (as_parameter) { + if (Py_EnterRecursiveCall("while processing _as_parameter_")) { + Py_DECREF(as_parameter); + return NULL; + } value = PyCSimpleType_from_param(type, as_parameter); + Py_LeaveRecursiveCall(); Py_DECREF(as_parameter); return value; } @@ -2714,6 +2741,7 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, Py_ssize_t size, char *ptr) { CDataObject *src; + int err; if (setfunc) return setfunc(ptr, value, size); @@ -2754,7 +2782,10 @@ _PyCData_set(CDataObject *dst, PyObject *type, SETFUNC setfunc, PyObject *value, } src = (CDataObject *)value; - if (PyObject_IsInstance(value, type)) { + err = PyObject_IsInstance(value, type); + if (err == -1) + return NULL; + if (err) { memcpy(ptr, src->b_ptr, size); @@ -4749,14 +4780,17 @@ Pointer_set_contents(CDataObject *self, PyObject *value, void *closure) stgdict = PyObject_stgdict((PyObject *)self); assert(stgdict); /* Cannot be NULL fr pointer instances */ assert(stgdict->proto); - if (!CDataObject_Check(value) - || 0 == PyObject_IsInstance(value, stgdict->proto)) { - /* XXX PyObject_IsInstance could return -1! */ - PyErr_Format(PyExc_TypeError, - "expected %s instead of %s", - ((PyTypeObject *)(stgdict->proto))->tp_name, - Py_TYPE(value)->tp_name); - return -1; + if (!CDataObject_Check(value)) { + int res = PyObject_IsInstance(value, stgdict->proto); + if (res == -1) + return -1; + if (!res) { + PyErr_Format(PyExc_TypeError, + "expected %s instead of %s", + ((PyTypeObject *)(stgdict->proto))->tp_name, + Py_TYPE(value)->tp_name); + return -1; + } } dst = (CDataObject *)value; |