[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