[pypy-commit] cffi default: Test and fix for an obscure case that raised SystemError instead of

arigo noreply at buildbot.pypy.org
Fri Jul 27 14:27:35 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r710:419181fc231b
Date: 2012-07-27 14:27 +0200
http://bitbucket.org/cffi/cffi/changeset/419181fc231b/

Log:	Test and fix for an obscure case that raised SystemError instead of
	the proper TypeError.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -3105,7 +3105,7 @@
         /* then enough room for the result --- which means at least
            sizeof(ffi_arg), according to the ffi docs */
         i = fb->rtype->size;
-        if (i < sizeof(ffi_arg))
+        if (i < (Py_ssize_t)sizeof(ffi_arg))
             i = sizeof(ffi_arg);
         exchange_offset += i;
     }
@@ -3361,7 +3361,17 @@
     /* work work work around a libffi irregularity: for integer return
        types we have to fill at least a complete 'ffi_arg'-sized result
        buffer. */
-    if (ctype->ct_size < sizeof(ffi_arg)) {
+    if (ctype->ct_size < (Py_ssize_t)sizeof(ffi_arg)) {
+        if (ctype->ct_flags & CT_VOID) {
+            if (pyobj == Py_None) {
+                return 0;
+            }
+            else {
+                PyErr_SetString(PyExc_TypeError,
+                    "callback with the return type 'void' must return None");
+                return -1;
+            }
+        }
         if ((ctype->ct_flags & (CT_PRIMITIVE_SIGNED | CT_IS_ENUM))
                 == CT_PRIMITIVE_SIGNED) {
             PY_LONG_LONG value;
@@ -3429,16 +3439,8 @@
     py_res = PyEval_CallObject(py_ob, py_args);
     if (py_res == NULL)
         goto error;
-
-    if (SIGNATURE(1)->ct_size > 0) {
-        if (convert_from_object_fficallback(result, SIGNATURE(1), py_res) < 0)
-            goto error;
-    }
-    else if (py_res != Py_None) {
-        PyErr_SetString(PyExc_TypeError, "callback with the return type 'void'"
-                                         " must return None");
+    if (convert_from_object_fficallback(result, SIGNATURE(1), py_res) < 0)
         goto error;
-    }
  done:
     Py_XDECREF(py_args);
     Py_XDECREF(py_res);
@@ -3487,14 +3489,8 @@
 
     ctresult = (CTypeDescrObject *)PyTuple_GET_ITEM(ct->ct_stuff, 1);
     size = ctresult->ct_size;
-    if (ctresult->ct_flags & (CT_PRIMITIVE_CHAR | CT_PRIMITIVE_SIGNED |
-                              CT_PRIMITIVE_UNSIGNED)) {
-        if (size < sizeof(ffi_arg))
-            size = sizeof(ffi_arg);
-    }
-    else if (size < 0) {
-        size = 0;
-    }
+    if (size < (Py_ssize_t)sizeof(ffi_arg))
+        size = sizeof(ffi_arg);
     py_rawerr = PyString_FromStringAndSize(NULL, size);
     if (py_rawerr == NULL)
         return NULL;
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -926,6 +926,17 @@
     assert s.a == -10
     assert s.b == 1E-42
 
+def test_callback_returning_void():
+    BVoid = new_void_type()
+    BFunc = new_function_type((), BVoid, False)
+    def cb():
+        seen.append(42)
+    f = callback(BFunc, cb)
+    seen = []
+    f()
+    assert seen == [42]
+    py.test.raises(TypeError, callback, BFunc, cb, -42)
+
 def test_enum_type():
     BEnum = new_enum_type("foo", (), ())
     assert repr(BEnum) == "<ctype 'enum foo'>"


More information about the pypy-commit mailing list