[pypy-commit] cffi default: Issue 200: bad interaction between "ffi.typeof(function_t)" and

arigo noreply at buildbot.pypy.org
Sat May 30 13:17:46 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r2131:83a960dee7ad
Date: 2015-05-30 13:18 +0200
http://bitbucket.org/cffi/cffi/changeset/83a960dee7ad/

Log:	Issue 200: bad interaction between "ffi.typeof(function_t)" and
	attribute access "lib.function"

diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -115,23 +115,30 @@
     struct CPyExtFunc_s *xfunc;
     int i, type_index = _CFFI_GETARG(g->type_op);
     _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
-    assert(_CFFI_GETOP(opcodes[type_index]) == _CFFI_OP_FUNCTION);
 
-    /* return type: */
-    ct = realize_c_type(lib->l_types_builder, opcodes,
-                        _CFFI_GETARG(opcodes[type_index]));
-    if (ct == NULL)
-        return NULL;
-    Py_DECREF(ct);
+    if ((((uintptr_t)opcodes[type_index]) & 1) == 0) {
+        /* the function type was already built.  No need to force
+           the arg and return value to be built again. */
+    }
+    else {
+        assert(_CFFI_GETOP(opcodes[type_index]) == _CFFI_OP_FUNCTION);
 
-    /* argument types: */
-    i = type_index + 1;
-    while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
-        ct = realize_c_type(lib->l_types_builder, opcodes, i);
+        /* return type: */
+        ct = realize_c_type(lib->l_types_builder, opcodes,
+                            _CFFI_GETARG(opcodes[type_index]));
         if (ct == NULL)
             return NULL;
         Py_DECREF(ct);
-        i++;
+
+        /* argument types: */
+        i = type_index + 1;
+        while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
+            ct = realize_c_type(lib->l_types_builder, opcodes, i);
+            if (ct == NULL)
+                return NULL;
+            Py_DECREF(ct);
+            i++;
+        }
     }
 
     /* xxx the few bytes of memory we allocate here leak, but it's a
diff --git a/c/realize_c_type.c b/c/realize_c_type.c
--- a/c/realize_c_type.c
+++ b/c/realize_c_type.c
@@ -536,6 +536,10 @@
 
         base_index = index + 1;
         num_args = 0;
+        /* note that if the arguments are already built, they have a
+           pointer in the 'opcodes' array, and GETOP() returns a
+           random even value.  But OP_FUNCTION_END is odd, so the
+           condition below still works correctly. */
         while (_CFFI_GETOP(opcodes[base_index + num_args]) !=
                    _CFFI_OP_FUNCTION_END)
             num_args++;
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -981,3 +981,16 @@
         static foo_t sum(foo_t x[]) { return x[0] + x[1]; }
     """)
     assert lib.sum([40.0, 2.25]) == 42.25
+
+def test_issue200():
+    ffi = FFI()
+    ffi.cdef("""
+        typedef void (function_t)(void*);
+        void function(void *);
+    """)
+    lib = verify(ffi, 'test_issue200', """
+        static void function(void *p) { (void)p; }
+    """)
+    ffi.typeof('function_t*')
+    lib.function(ffi.NULL)
+    # assert did not crash


More information about the pypy-commit mailing list