[pypy-commit] cffi calculate_variable_array_length: When using a variable length struct, calculate and enforce the length of the varsized_array when accessing this field.

coronafire pypy.commits at gmail.com
Wed Oct 19 02:53:32 EDT 2016


Author: Andrew Leech <andrew at alelec.net>
Branch: calculate_variable_array_length
Changeset: r2789:d269f72d4a9a
Date: 2016-09-13 09:19 +1000
http://bitbucket.org/cffi/cffi/changeset/d269f72d4a9a/

Log:	When using a variable length struct, calculate and enforce the
	length of the varsized_array when accessing this field.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -906,6 +906,23 @@
     return (PyObject *)cd;
 }
 
+static PyObject *
+new_sized_cdata(char *data, CTypeDescrObject *ct, Py_ssize_t length)
+{
+    CDataObject_own_length *scd;
+    
+    scd = (CDataObject_own_length *)PyObject_Malloc(
+        offsetof(CDataObject_own_length, alignment));
+    if (PyObject_Init((PyObject *)scd, &CData_Type) == NULL)
+        return NULL;
+    Py_INCREF(ct);
+    scd->head.c_type = ct;
+    scd->head.c_data = data;
+    scd->head.c_weakreflist = NULL;
+    scd->length = length;
+    return (PyObject *)scd;
+}
+
 static CDataObject *_new_casted_primitive(CTypeDescrObject *ct);  /*forward*/
 
 static PyObject *
@@ -2387,7 +2404,15 @@
             if (cf != NULL) {
                 /* read the field 'cf' */
                 char *data = cd->c_data + cf->cf_offset;
-                if (cf->cf_bitshift == BS_REGULAR)
+
+                if ((cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) &&  // Is owned struct (or union)
+                    (cf->cf_type->ct_flags & CT_ARRAY) &&  // field is an array
+                    (cf->cf_type->ct_size == -1)) { // unknown length array
+                    /* if reading variable length array from variable length struct, calculate array type from allocated length*/
+                    Py_ssize_t array_len = (((CDataObject_own_structptr *)cd)->length - ct->ct_size) / cf->cf_type->ct_itemdescr->ct_size;
+                    return new_sized_cdata(data, cf->cf_type, array_len);
+                }
+                else if (cf->cf_bitshift == BS_REGULAR)
                     return convert_to_object(data, cf->cf_type);
                 else if (cf->cf_bitshift == BS_EMPTY_ARRAY)
                     return new_simple_cdata(data,


More information about the pypy-commit mailing list