python: Do not depend on access to internal data structures.
* lang/python/gpgme.i (gpgme_data_t): Rework so that it works without access to the definition of 'struct gpgme_data'. * lang/python/helpers.c (object_to_gpgme_data_t): Add assertion. Signed-off-by: Justus Winter <justus@g10code.com>
This commit is contained in:
parent
c53f87c5f9
commit
98cba522c9
@ -125,7 +125,8 @@
|
|||||||
|
|
||||||
// Special handling for references to our objects.
|
// Special handling for references to our objects.
|
||||||
%typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL,
|
%typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL,
|
||||||
PyObject *bytesio = NULL, Py_buffer view) {
|
PyObject *bytesio = NULL,
|
||||||
|
Py_buffer view, int have_view = 0) {
|
||||||
/* If we create a temporary wrapper object, we will store it in
|
/* If we create a temporary wrapper object, we will store it in
|
||||||
wrapperN, where N is $argnum. Here in this fragment, SWIG will
|
wrapperN, where N is $argnum. Here in this fragment, SWIG will
|
||||||
automatically append $argnum. */
|
automatically append $argnum. */
|
||||||
@ -138,6 +139,7 @@
|
|||||||
&bytesio, &view);
|
&bytesio, &view);
|
||||||
if (pypointer == NULL)
|
if (pypointer == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
have_view = !! view.obj;
|
||||||
|
|
||||||
/* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
|
/* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
|
||||||
|
|
||||||
@ -152,79 +154,108 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_DATA_H
|
||||||
|
/* If we are doing an in-tree build, we can use the internal
|
||||||
|
representation of struct gpgme_data for an very efficient check if
|
||||||
|
the buffer has been modified. */
|
||||||
|
%{
|
||||||
|
#include "src/data.h" /* For struct gpgme_data. */
|
||||||
|
%}
|
||||||
|
#endif
|
||||||
|
|
||||||
%typemap(freearg) gpgme_data_t DATAIN {
|
%typemap(freearg) gpgme_data_t DATAIN {
|
||||||
/* See whether we need to update the Python buffer. */
|
/* See whether we need to update the Python buffer. */
|
||||||
if (resultobj && wrapper$argnum && view$argnum.buf
|
if (resultobj && wrapper$argnum && view$argnum.buf)
|
||||||
&& wrapper$argnum->data.mem.buffer != NULL)
|
|
||||||
{
|
{
|
||||||
/* The buffer is dirty. */
|
int dirty;
|
||||||
if (view$argnum.readonly)
|
char *new_data = NULL;
|
||||||
{
|
size_t new_size;
|
||||||
Py_XDECREF(resultobj);
|
|
||||||
resultobj = NULL;
|
|
||||||
PyErr_SetString(PyExc_ValueError, "cannot update read-only buffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if we need to truncate the buffer. */
|
#if HAVE_DATA_H
|
||||||
if (resultobj && view$argnum.len != wrapper$argnum->data.mem.length)
|
new_data = wrapper$argnum->data.mem.buffer;
|
||||||
|
new_size = wrapper$argnum->data.mem.length;
|
||||||
|
dirty = new_data != NULL;
|
||||||
|
#else
|
||||||
|
new_data = gpgme_data_release_and_get_mem (wrapper$argnum, &new_size);
|
||||||
|
wrapper$argnum = NULL;
|
||||||
|
dirty = new_size != view$argnum.len
|
||||||
|
|| memcmp (new_data, view$argnum.buf, view$argnum.len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (dirty)
|
||||||
{
|
{
|
||||||
if (bytesio$argnum == NULL)
|
/* The buffer is dirty. */
|
||||||
|
if (view$argnum.readonly)
|
||||||
{
|
{
|
||||||
Py_XDECREF(resultobj);
|
Py_XDECREF(resultobj);
|
||||||
resultobj = NULL;
|
resultobj = NULL;
|
||||||
PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"cannot update read-only buffer");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
/* See if we need to truncate the buffer. */
|
||||||
|
if (resultobj && view$argnum.len != new_size)
|
||||||
{
|
{
|
||||||
PyObject *retval;
|
if (bytesio$argnum == NULL)
|
||||||
PyBuffer_Release(&view$argnum);
|
|
||||||
retval = PyObject_CallMethod(bytesio$argnum, "truncate", "l",
|
|
||||||
(long)
|
|
||||||
wrapper$argnum->data.mem.length);
|
|
||||||
if (retval == NULL)
|
|
||||||
{
|
{
|
||||||
Py_XDECREF(resultobj);
|
Py_XDECREF(resultobj);
|
||||||
resultobj = NULL;
|
resultobj = NULL;
|
||||||
|
PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Py_DECREF(retval);
|
PyObject *retval;
|
||||||
|
PyBuffer_Release(&view$argnum);
|
||||||
retval = PyObject_CallMethod(bytesio$argnum, "getbuffer", NULL);
|
assert(view$argnum.obj == NULL);
|
||||||
if (retval == NULL
|
retval = PyObject_CallMethod(bytesio$argnum, "truncate",
|
||||||
|| PyObject_GetBuffer(retval, &view$argnum,
|
"l", (long) new_size);
|
||||||
PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
|
if (retval == NULL)
|
||||||
{
|
{
|
||||||
Py_XDECREF(resultobj);
|
Py_XDECREF(resultobj);
|
||||||
resultobj = NULL;
|
resultobj = NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
Py_XDECREF(retval);
|
|
||||||
|
|
||||||
if (resultobj && view$argnum.len
|
|
||||||
!= wrapper$argnum->data.mem.length)
|
|
||||||
{
|
{
|
||||||
Py_XDECREF(resultobj);
|
Py_DECREF(retval);
|
||||||
resultobj = NULL;
|
|
||||||
PyErr_Format(PyExc_ValueError,
|
retval = PyObject_CallMethod(bytesio$argnum,
|
||||||
"Expected buffer of length %zu, got %zi",
|
"getbuffer", NULL);
|
||||||
wrapper$argnum->data.mem.length,
|
if (retval == NULL
|
||||||
view$argnum.len);
|
|| PyObject_GetBuffer(retval, &view$argnum,
|
||||||
|
PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
|
||||||
|
{
|
||||||
|
Py_XDECREF(resultobj);
|
||||||
|
resultobj = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_XDECREF(retval);
|
||||||
|
|
||||||
|
if (resultobj && view$argnum.len
|
||||||
|
!= new_size)
|
||||||
|
{
|
||||||
|
Py_XDECREF(resultobj);
|
||||||
|
resultobj = NULL;
|
||||||
|
PyErr_Format(PyExc_ValueError,
|
||||||
|
"Expected buffer of length %zu, got %zi",
|
||||||
|
new_size,
|
||||||
|
view$argnum.len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (resultobj)
|
||||||
|
memcpy(view$argnum.buf, new_data, new_size);
|
||||||
}
|
}
|
||||||
|
#if ! HAVE_DATA_H
|
||||||
if (resultobj)
|
free (new_data);
|
||||||
memcpy(view$argnum.buf, wrapper$argnum->data.mem.buffer,
|
#endif
|
||||||
wrapper$argnum->data.mem.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free the temporary wrapper, if any. */
|
/* Free the temporary wrapper, if any. */
|
||||||
if (wrapper$argnum)
|
if (wrapper$argnum)
|
||||||
gpgme_data_release(wrapper$argnum);
|
gpgme_data_release(wrapper$argnum);
|
||||||
Py_XDECREF (bytesio$argnum);
|
Py_XDECREF (bytesio$argnum);
|
||||||
if (wrapper$argnum && view$argnum.buf)
|
if (have_view$argnum && view$argnum.buf)
|
||||||
PyBuffer_Release(&view$argnum);
|
PyBuffer_Release(&view$argnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +429,6 @@
|
|||||||
SWIG. */
|
SWIG. */
|
||||||
%{
|
%{
|
||||||
#include <gpgme.h>
|
#include <gpgme.h>
|
||||||
#include "src/data.h" /* For struct gpgme_data. */
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
/* This is for notations, where we want to hide the length fields, and
|
/* This is for notations, where we want to hide the length fields, and
|
||||||
|
@ -254,6 +254,7 @@ object_to_gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
|
|||||||
if (data != input)
|
if (data != input)
|
||||||
Py_DECREF(data);
|
Py_DECREF(data);
|
||||||
|
|
||||||
|
assert (view->obj);
|
||||||
assert (view->ndim == 1);
|
assert (view->ndim == 1);
|
||||||
assert (view->shape == NULL);
|
assert (view->shape == NULL);
|
||||||
assert (view->strides == NULL);
|
assert (view->strides == NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user