[pypy-commit] pypy default: update to cffi/ff25b4e68195
arigo
pypy.commits at gmail.com
Mon Mar 11 05:48:14 EDT 2019
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r96269:fd0c6116edcd
Date: 2019-03-11 10:46 +0100
http://bitbucket.org/pypy/pypy/changeset/fd0c6116edcd/
Log: update to cffi/ff25b4e68195
diff --git a/pypy/module/_cffi_backend/ctypestruct.py b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
+++ b/pypy/module/_cffi_backend/ctypestruct.py
@@ -238,26 +238,32 @@
else:
self.ctype.convert_from_object(cdata, w_ob)
+ def add_varsize_length(self, space, itemsize, varsizelength, optvarsize):
+ # returns an updated 'optvarsize' to account for an array of
+ # 'varsizelength' elements, each of size 'itemsize', that starts
+ # at 'self.offset'.
+ try:
+ varsize = ovfcheck(itemsize * varsizelength)
+ size = ovfcheck(self.offset + varsize)
+ except OverflowError:
+ raise oefmt(space.w_OverflowError,
+ "array size would overflow a ssize_t")
+ assert size >= 0
+ return max(size, optvarsize)
+
def write_v(self, cdata, w_ob, optvarsize):
# a special case for var-sized C99 arrays
from pypy.module._cffi_backend import ctypearray
ct = self.ctype
+ space = ct.space
if isinstance(ct, ctypearray.W_CTypeArray) and ct.length < 0:
- space = ct.space
w_ob, varsizelength = ct.get_new_array_length(w_ob)
if optvarsize != -1:
# in this mode, the only purpose of this function is to compute
# the real size of the structure from a var-sized C99 array
assert cdata == lltype.nullptr(rffi.CCHARP.TO)
- itemsize = ct.ctitem.size
- try:
- varsize = ovfcheck(itemsize * varsizelength)
- size = ovfcheck(self.offset + varsize)
- except OverflowError:
- raise oefmt(space.w_OverflowError,
- "array size would overflow a ssize_t")
- assert size >= 0
- return max(size, optvarsize)
+ return self.add_varsize_length(space, ct.ctitem.size,
+ varsizelength, optvarsize)
# if 'value' was only an integer, get_new_array_length() returns
# w_ob = space.w_None. Detect if this was the case,
# and if so, stop here, leaving the content uninitialized
@@ -267,6 +273,12 @@
#
if optvarsize == -1:
self.write(cdata, w_ob)
+ elif (isinstance(ct, W_CTypeStructOrUnion) and ct._with_var_array and
+ not isinstance(w_ob, cdataobj.W_CData)):
+ subsize = ct.size
+ subsize = ct.convert_struct_from_object(
+ lltype.nullptr(rffi.CCHARP.TO), w_ob, subsize)
+ optvarsize = self.add_varsize_length(space, 1, subsize, optvarsize)
return optvarsize
def convert_bitfield_to_object(self, cdata):
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -368,6 +368,16 @@
raise oefmt(space.w_TypeError,
"field '%s.%s' has ctype '%s' of unknown size",
w_ctype.name, fname, ftype.name)
+ elif isinstance(ftype, ctypestruct.W_CTypeStructOrUnion):
+ ftype.force_lazy_struct()
+ # GCC (or maybe C99) accepts var-sized struct fields that are not
+ # the last field of a larger struct. That's why there is no
+ # check here for "last field": we propagate the flag
+ # '_with_var_array' to any struct that contains either an open-
+ # ended array or another struct that recursively contains an
+ # open-ended array.
+ if ftype._with_var_array:
+ with_var_array = True
#
if is_union:
boffset = 0 # reset each field at offset 0
@@ -419,7 +429,6 @@
# a nested anonymous struct or union
# note: it seems we only get here with ffi.verify()
srcfield2names = {}
- ftype.force_lazy_struct()
for name, srcfld in ftype._fields_dict.items():
srcfield2names[srcfld] = name
for srcfld in ftype._fields_list:
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -3441,6 +3441,15 @@
assert p.a[1] == 20
assert p.a[2] == 30
assert p.a[3] == 0
+ #
+ # struct of struct of varsized array
+ BStruct2 = new_struct_type("bar")
+ complete_struct_or_union(BStruct2, [('head', BInt),
+ ('tail', BStruct)])
+ for i in range(2): # try to detect heap overwrites
+ p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]])
+ assert p.tail.y[49] == 49
+
def test_struct_array_no_length_explicit_position():
BInt = new_primitive_type("int")
More information about the pypy-commit
mailing list