summaryrefslogtreecommitdiff
path: root/c/_cffi_backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/_cffi_backend.c')
-rw-r--r--c/_cffi_backend.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index ffecbf9..b9618bd 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -2,7 +2,7 @@
#include <Python.h>
#include "structmember.h"
-#define CFFI_VERSION "1.15.0"
+#define CFFI_VERSION "1.15.1"
#ifdef MS_WIN32
#include <windows.h>
@@ -2197,7 +2197,7 @@ static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name)
}
}
-static PyObject *cdataowning_repr(CDataObject *cd)
+static Py_ssize_t cdataowning_size_bytes(CDataObject *cd)
{
Py_ssize_t size = _cdata_var_byte_size(cd);
if (size < 0) {
@@ -2208,6 +2208,12 @@ static PyObject *cdataowning_repr(CDataObject *cd)
else
size = cd->c_type->ct_size;
}
+ return size;
+}
+
+static PyObject *cdataowning_repr(CDataObject *cd)
+{
+ Py_ssize_t size = cdataowning_size_bytes(cd);
return PyText_FromFormat("<cdata '%s' owning %zd bytes>",
cd->c_type->ct_name, size);
}
@@ -4603,7 +4609,7 @@ static PyObject *get_unique_type(CTypeDescrObject *x,
array [ctype, length]
funcptr [ctresult, ellipsis+abi, num_args, ctargs...]
*/
- PyObject *key, *y;
+ PyObject *key, *y, *res;
void *pkey;
key = PyBytes_FromStringAndSize(NULL, keylength * sizeof(void *));
@@ -4635,8 +4641,9 @@ static PyObject *get_unique_type(CTypeDescrObject *x,
/* the 'value' in unique_cache doesn't count as 1, but don't use
Py_DECREF(x) here because it will confuse debug builds into thinking
there was an extra DECREF in total. */
- ((PyObject *)x)->ob_refcnt--;
- return (PyObject *)x;
+ res = (PyObject *)x;
+ Py_SET_REFCNT(res, Py_REFCNT(res) - 1);
+ return res;
error:
Py_DECREF(x);
@@ -5665,7 +5672,8 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
}
}
-#define ALIGN_ARG(n) ((n) + 7) & ~7
+#define ALIGN_TO(n, a) ((n) + ((a)-1)) & ~((a)-1)
+#define ALIGN_ARG(n) ALIGN_TO(n, 8)
static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
CTypeDescrObject *fresult)
@@ -5690,10 +5698,12 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
/* exchange data size */
/* first, enough room for an array of 'nargs' pointers */
exchange_offset = nargs * sizeof(void*);
+ /* then enough room for the result --- which means at least
+ sizeof(ffi_arg), according to the ffi docs, but we also
+ align according to the result type, for issue #531 */
+ exchange_offset = ALIGN_TO(exchange_offset, fb->rtype->alignment);
exchange_offset = ALIGN_ARG(exchange_offset);
cif_descr->exchange_offset_arg[0] = exchange_offset;
- /* then enough room for the result --- which means at least
- sizeof(ffi_arg), according to the ffi docs */
i = fb->rtype->size;
if (i < (Py_ssize_t)sizeof(ffi_arg))
i = sizeof(ffi_arg);
@@ -5721,6 +5731,7 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
if (fb->atypes != NULL) {
fb->atypes[i] = atype;
/* exchange data size */
+ exchange_offset = ALIGN_TO(exchange_offset, atype->alignment);
exchange_offset = ALIGN_ARG(exchange_offset);
cif_descr->exchange_offset_arg[1 + i] = exchange_offset;
exchange_offset += atype->size;
@@ -5737,6 +5748,7 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
}
#undef ALIGN_ARG
+#undef ALIGN_TO
static void fb_cat_name(struct funcbuilder_s *fb, const char *piece,
int piecelen)
@@ -7010,12 +7022,14 @@ b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* this is the constructor of the type implemented in minibuffer.h */
CDataObject *cd;
Py_ssize_t size = -1;
+ int explicit_size;
static char *keywords[] = {"cdata", "size", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:buffer", keywords,
&CData_Type, &cd, &size))
return NULL;
+ explicit_size = size >= 0;
if (size < 0)
size = _cdata_var_byte_size(cd);
@@ -7039,6 +7053,20 @@ b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
cd->c_type->ct_name);
return NULL;
}
+
+ if (explicit_size && CDataOwn_Check(cd)) {
+ Py_ssize_t size_max = cdataowning_size_bytes(cd);
+ if (size > size_max) {
+ char msg[256];
+ sprintf(msg, "ffi.buffer(cdata, bytes): creating a buffer of %llu "
+ "bytes over a cdata that owns only %llu bytes. This "
+ "will crash if you access the extra memory",
+ (unsigned PY_LONG_LONG)size,
+ (unsigned PY_LONG_LONG)size_max);
+ if (PyErr_WarnEx(PyExc_UserWarning, msg, 1))
+ return NULL;
+ }
+ }
/*WRITE(cd->c_data, size)*/
return minibuffer_new(cd->c_data, size, (PyObject *)cd);
}