22#include <Python.h>
33#include "structmember.h"
44
5- #define CFFI_VERSION "1.15.0 "
5+ #define CFFI_VERSION "1.15.1 "
66
77#ifdef MS_WIN32
88#include <windows.h>
@@ -2197,7 +2197,7 @@ static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name)
21972197 }
21982198}
21992199
2200- static PyObject * cdataowning_repr (CDataObject * cd )
2200+ static Py_ssize_t cdataowning_size_bytes (CDataObject * cd )
22012201{
22022202 Py_ssize_t size = _cdata_var_byte_size (cd );
22032203 if (size < 0 ) {
@@ -2208,6 +2208,12 @@ static PyObject *cdataowning_repr(CDataObject *cd)
22082208 else
22092209 size = cd -> c_type -> ct_size ;
22102210 }
2211+ return size ;
2212+ }
2213+
2214+ static PyObject * cdataowning_repr (CDataObject * cd )
2215+ {
2216+ Py_ssize_t size = cdataowning_size_bytes (cd );
22112217 return PyText_FromFormat ("<cdata '%s' owning %zd bytes>" ,
22122218 cd -> c_type -> ct_name , size );
22132219}
@@ -4603,7 +4609,7 @@ static PyObject *get_unique_type(CTypeDescrObject *x,
46034609 array [ctype, length]
46044610 funcptr [ctresult, ellipsis+abi, num_args, ctargs...]
46054611 */
4606- PyObject * key , * y ;
4612+ PyObject * key , * y , * res ;
46074613 void * pkey ;
46084614
46094615 key = PyBytes_FromStringAndSize (NULL , keylength * sizeof (void * ));
@@ -4635,8 +4641,9 @@ static PyObject *get_unique_type(CTypeDescrObject *x,
46354641 /* the 'value' in unique_cache doesn't count as 1, but don't use
46364642 Py_DECREF(x) here because it will confuse debug builds into thinking
46374643 there was an extra DECREF in total. */
4638- ((PyObject * )x )-> ob_refcnt -- ;
4639- return (PyObject * )x ;
4644+ res = (PyObject * )x ;
4645+ Py_SET_REFCNT (res , Py_REFCNT (res ) - 1 );
4646+ return res ;
46404647
46414648 error :
46424649 Py_DECREF (x );
@@ -5665,7 +5672,8 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
56655672 }
56665673}
56675674
5668- #define ALIGN_ARG (n ) ((n) + 7) & ~7
5675+ #define ALIGN_TO (n , a ) ((n) + ((a)-1)) & ~((a)-1)
5676+ #define ALIGN_ARG (n ) ALIGN_TO(n, 8)
56695677
56705678static int fb_build (struct funcbuilder_s * fb , PyObject * fargs ,
56715679 CTypeDescrObject * fresult )
@@ -5690,10 +5698,12 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
56905698 /* exchange data size */
56915699 /* first, enough room for an array of 'nargs' pointers */
56925700 exchange_offset = nargs * sizeof (void * );
5701+ /* then enough room for the result --- which means at least
5702+ sizeof(ffi_arg), according to the ffi docs, but we also
5703+ align according to the result type, for issue #531 */
5704+ exchange_offset = ALIGN_TO (exchange_offset , fb -> rtype -> alignment );
56935705 exchange_offset = ALIGN_ARG (exchange_offset );
56945706 cif_descr -> exchange_offset_arg [0 ] = exchange_offset ;
5695- /* then enough room for the result --- which means at least
5696- sizeof(ffi_arg), according to the ffi docs */
56975707 i = fb -> rtype -> size ;
56985708 if (i < (Py_ssize_t )sizeof (ffi_arg ))
56995709 i = sizeof (ffi_arg );
@@ -5721,6 +5731,7 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
57215731 if (fb -> atypes != NULL ) {
57225732 fb -> atypes [i ] = atype ;
57235733 /* exchange data size */
5734+ exchange_offset = ALIGN_TO (exchange_offset , atype -> alignment );
57245735 exchange_offset = ALIGN_ARG (exchange_offset );
57255736 cif_descr -> exchange_offset_arg [1 + i ] = exchange_offset ;
57265737 exchange_offset += atype -> size ;
@@ -5737,6 +5748,7 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
57375748}
57385749
57395750#undef ALIGN_ARG
5751+ #undef ALIGN_TO
57405752
57415753static void fb_cat_name (struct funcbuilder_s * fb , const char * piece ,
57425754 int piecelen )
@@ -7010,12 +7022,14 @@ b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
70107022 /* this is the constructor of the type implemented in minibuffer.h */
70117023 CDataObject * cd ;
70127024 Py_ssize_t size = -1 ;
7025+ int explicit_size ;
70137026 static char * keywords [] = {"cdata" , "size" , NULL };
70147027
70157028 if (!PyArg_ParseTupleAndKeywords (args , kwds , "O!|n:buffer" , keywords ,
70167029 & CData_Type , & cd , & size ))
70177030 return NULL ;
70187031
7032+ explicit_size = size >= 0 ;
70197033 if (size < 0 )
70207034 size = _cdata_var_byte_size (cd );
70217035
@@ -7039,6 +7053,20 @@ b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
70397053 cd -> c_type -> ct_name );
70407054 return NULL ;
70417055 }
7056+
7057+ if (explicit_size && CDataOwn_Check (cd )) {
7058+ Py_ssize_t size_max = cdataowning_size_bytes (cd );
7059+ if (size > size_max ) {
7060+ char msg [256 ];
7061+ sprintf (msg , "ffi.buffer(cdata, bytes): creating a buffer of %llu "
7062+ "bytes over a cdata that owns only %llu bytes. This "
7063+ "will crash if you access the extra memory" ,
7064+ (unsigned PY_LONG_LONG )size ,
7065+ (unsigned PY_LONG_LONG )size_max );
7066+ if (PyErr_WarnEx (PyExc_UserWarning , msg , 1 ))
7067+ return NULL ;
7068+ }
7069+ }
70427070 /*WRITE(cd->c_data, size)*/
70437071 return minibuffer_new (cd -> c_data , size , (PyObject * )cd );
70447072}
0 commit comments