[Python-checkins] cpython (merge 3.2 -> default): merge 3.2

benjamin.peterson python-checkins at python.org
Sun Mar 27 00:17:04 CET 2011


http://hg.python.org/cpython/rev/b44156fdc7f2
changeset:   68998:b44156fdc7f2
parent:      68988:8bdc20468cbc
parent:      68997:d5c819d597fe
user:        Benjamin Peterson <benjamin at python.org>
date:        Sat Mar 26 18:18:09 2011 -0500
summary:
  merge 3.2

files:
  Lib/ctypes/test/test_as_parameter.py |  12 ++
  Misc/NEWS                            |   6 +
  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
--- a/Lib/ctypes/test/test_as_parameter.py
+++ b/Lib/ctypes/test/test_as_parameter.py
@@ -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):
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -322,6 +322,12 @@
 
 - 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
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -585,7 +585,10 @@
 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 @@
 
         /* 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 @@
         Py_INCREF(value); /* _byref steals a refcount */
         return _byref(value);
     case -1:
-        PyErr_Clear();
-        break;
+        return NULL;
     default:
         break;
     }
@@ -1431,6 +1437,7 @@
 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 @@
         }
         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 @@
 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 @@
         }
         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 @@
 {
     StgDictObject *stgd;
     PyObject *as_parameter;
+    int res;
 
 /* None */
     if (value == Py_None) {
@@ -1631,7 +1646,10 @@
         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 @@
     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 @@
 
     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 @@
            Py_ssize_t size, char *ptr)
 {
     CDataObject *src;
+    int err;
 
     if (setfunc)
         return setfunc(ptr, value, size);
@@ -2754,7 +2782,10 @@
     }
     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 @@
     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;

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list