[pypy-commit] cffi cpy-extension: Detect mismatches in the size of fields.
arigo
noreply at buildbot.pypy.org
Wed Jun 13 10:18:03 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: cpy-extension
Changeset: r304:cd82a84cd16b
Date: 2012-06-13 10:17 +0200
http://bitbucket.org/cffi/cffi/changeset/cd82a84cd16b/
Log: Detect mismatches in the size of fields.
diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -2321,8 +2321,8 @@
if (ftype->ct_size < 0) {
PyErr_Format(PyExc_TypeError,
- "field '%s' has ctype '%s' of unknown size",
- PyString_AS_STRING(fname),
+ "field '%s.%s' has ctype '%s' of unknown size",
+ ct->ct_name, PyString_AS_STRING(fname),
ftype->ct_name);
goto error;
}
diff --git a/cffi/model.py b/cffi/model.py
--- a/cffi/model.py
+++ b/cffi/model.py
@@ -153,7 +153,14 @@
lst = zip(self.fldnames, fldtypes, self.fldbitsize)
ffi._backend.complete_struct_or_union(BType, lst, self)
else:
- fieldofs, totalsize, totalalignment = self.fixedlayout
+ fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout
+ for fname, ftype, fsize in zip(self.fldnames, fldtypes, fieldsize):
+ if ffi.sizeof(ftype) != fsize:
+ from .ffiplatform import VerificationError
+ raise VerificationError, (
+ "field '%s.%s' is declared as %d bytes, but is "
+ "really %d bytes" % (self.name, fname,
+ ffi.sizeof(ftype), fsize))
lst = zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)
ffi._backend.complete_struct_or_union(BType, lst, self,
totalsize, totalalignment)
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -69,10 +69,8 @@
module._cffi_setup(lst)
del module._cffi_setup
#
- for name, tp in self.ffi._parser._declarations.iteritems():
- kind, realname = name.split(' ', 1)
- method = getattr(self, 'loading_cpy_%s' % (kind,))
- method(tp, realname, module)
+ self.load(module, 'loading')
+ self.load(module, 'loaded')
#
return module
@@ -82,6 +80,12 @@
method = getattr(self, 'generate_cpy_%s_%s' % (kind, step_name))
method(tp, realname)
+ def load(self, module, step_name):
+ for name, tp in self.ffi._parser._declarations.iteritems():
+ kind, realname = name.split(' ', 1)
+ method = getattr(self, '%s_cpy_%s' % (step_name, kind))
+ method(tp, realname, module)
+
def generate_nothing(self, tp, name):
pass
@@ -130,6 +134,7 @@
generate_cpy_typedef_method = generate_nothing
generate_cpy_typedef_init = generate_nothing
loading_cpy_typedef = loaded_noop
+ loaded_cpy_typedef = loaded_noop
# ----------
# function declarations
@@ -198,11 +203,13 @@
generate_cpy_function_init = generate_nothing
loading_cpy_function = loaded_noop
+ loaded_cpy_function = loaded_noop
# ----------
# struct declarations
def generate_cpy_struct_decl(self, tp, name):
+ assert tp.partial # xxx
assert name == tp.name
prnt = self.prnt
prnt('static PyObject *')
@@ -214,6 +221,7 @@
prnt(' offsetof(struct _cffi_aligncheck, y),')
for i in range(len(tp.fldnames)):
prnt(' offsetof(struct %s, %s),' % (name, tp.fldnames[i]))
+ prnt(' sizeof(((struct %s *)0)->%s),' % (name, tp.fldnames[i]))
prnt(' -1')
prnt(' };')
prnt(' return _cffi_get_struct_layout(nums);')
@@ -231,9 +239,13 @@
layout = function()
totalsize = layout[0]
totalalignment = layout[1]
- fieldofs = layout[2:]
- assert len(fieldofs) == len(tp.fldnames)
- tp.fixedlayout = fieldofs, totalsize, totalalignment
+ fieldofs = layout[2::2]
+ fieldsize = layout[3::2]
+ assert len(fieldofs) == len(fieldsize) == len(tp.fldnames)
+ tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment
+
+ def loaded_cpy_struct(self, tp, name, module):
+ self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered
# ----------
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -47,6 +47,8 @@
'signed char', 'unsigned char',
'unsigned short', 'unsigned int',
'unsigned long', 'unsigned long long']
+all_signed_integer_types = [_typename for _typename in all_integer_types
+ if not _typename.startswith('unsigned ')]
all_float_types = ['float', 'double']
def test_all_integer_and_float_types():
@@ -164,3 +166,23 @@
""")
assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int')
assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int')
+
+def test_ffi_nonfull_alignment():
+ ffi = FFI()
+ ffi.cdef("struct foo_s { char x; ...; };")
+ ffi.verify("struct foo_s { int a, b; char x; };")
+ assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int')
+ assert ffi.alignof('struct foo_s') == ffi.sizeof('int')
+
+def test_struct_bad_sized_integer():
+ for typename in all_signed_integer_types:
+ for real in all_signed_integer_types:
+ ffi = FFI()
+ if ffi.sizeof(typename) != ffi.sizeof(real):
+ ffi.cdef("struct foo_s { %s x; ...; };" % typename)
+ try:
+ ffi.verify("struct foo_s { %s x; };" % real)
+ except VerificationError:
+ pass
+ else:
+ raise AssertionError("%s != %s" % (typename, real))
More information about the pypy-commit
mailing list