diff options
author | Armin Rigo <arigo@tunes.org> | 2016-07-31 15:07:56 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2016-07-31 15:07:56 +0200 |
commit | 9e68ee5e7c7824f5744f7f222c844885468c443e (patch) | |
tree | 5bdd7f2290655dab557227811cb9448fae4c7e82 | |
parent | bbae5839c3c0ae7f1ee6792ef2e4adf63f9acbc2 (diff) | |
download | cffi-9e68ee5e7c7824f5744f7f222c844885468c443e.tar.gz |
Test and fix: refuse to 'recompile' a cdef that declares a struct
with an opaque struct as a field
-rw-r--r-- | cffi/recompiler.py | 9 | ||||
-rw-r--r-- | testing/cffi1/test_recompiler.py | 32 |
2 files changed, 41 insertions, 0 deletions
diff --git a/cffi/recompiler.py b/cffi/recompiler.py index 0aed988..eb7c891 100644 --- a/cffi/recompiler.py +++ b/cffi/recompiler.py @@ -862,6 +862,8 @@ class Recompiler: enumfields = list(tp.enumfields()) for fldname, fldtype, fbitsize, fqual in enumfields: fldtype = self._field_type(tp, fldname, fldtype) + self._check_not_opaque(fldtype, + "field '%s.%s'" % (tp.name, fldname)) # cname is None for _add_missing_struct_unions() only op = OP_NOOP if fbitsize >= 0: @@ -911,6 +913,13 @@ class Recompiler: first_field_index, c_fields)) self._seen_struct_unions.add(tp) + def _check_not_opaque(self, tp, location): + while isinstance(tp, model.ArrayType): + tp = tp.item + if isinstance(tp, model.StructOrUnion) and tp.fldtypes is None: + raise TypeError( + "%s is of an opaque type (not declared in cdef())" % location) + def _add_missing_struct_unions(self): # not very nice, but some struct declarations might be missing # because they don't have any known C name. Check that they are diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py index 1bd1da2..d1fadfc 100644 --- a/testing/cffi1/test_recompiler.py +++ b/testing/cffi1/test_recompiler.py @@ -1918,3 +1918,35 @@ def test_bool_in_cpp(): ffi.cdef("bool f(void);") lib = verify(ffi, "test_bool_in_cpp", "char f(void) { return 2; }") assert lib.f() == 1 + +def test_struct_field_opaque(): + ffi = FFI() + ffi.cdef("struct a { struct b b; };") + e = py.test.raises(TypeError, verify, + ffi, "test_struct_field_opaque", "?") + assert str(e.value) == ("struct a: field 'a.b' is of an opaque" + " type (not declared in cdef())") + ffi = FFI() + ffi.cdef("struct a { struct b b[2]; };") + e = py.test.raises(TypeError, verify, + ffi, "test_struct_field_opaque", "?") + assert str(e.value) == ("struct a: field 'a.b' is of an opaque" + " type (not declared in cdef())") + ffi = FFI() + ffi.cdef("struct a { struct b b[]; };") + e = py.test.raises(TypeError, verify, + ffi, "test_struct_field_opaque", "?") + assert str(e.value) == ("struct a: field 'a.b' is of an opaque" + " type (not declared in cdef())") + +def test_function_arg_opaque(): + py.test.skip("can currently declare a function with an opaque struct " + "as argument, but AFAICT it's impossible to call it later") + +def test_function_returns_opaque(): + ffi = FFI() + ffi.cdef("struct a foo(int);") + e = py.test.raises(TypeError, verify, + ffi, "test_function_returns_opaque", "?") + assert str(e.value) == ("function foo: 'struct a' is used as result type," + " but is opaque") |