aboutsummaryrefslogtreecommitdiffstats
path: root/lang/python
diff options
context:
space:
mode:
authorJustus Winter <[email protected]>2016-07-11 14:34:15 +0000
committerJustus Winter <[email protected]>2016-07-11 15:50:58 +0000
commit98cba522c906115efcba1f8cc0bec7e5edb51ecd (patch)
treef7c9a12d934907e3b3eab109f745dfb0f9d9fe77 /lang/python
parentpython: Make result wrapping backwards compatible. (diff)
downloadgpgme-98cba522c906115efcba1f8cc0bec7e5edb51ecd.tar.gz
gpgme-98cba522c906115efcba1f8cc0bec7e5edb51ecd.zip
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 <[email protected]>
Diffstat (limited to 'lang/python')
-rw-r--r--lang/python/gpgme.i120
-rw-r--r--lang/python/helpers.c1
2 files changed, 76 insertions, 45 deletions
diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i
index 8dbb0c2c..c1e00740 100644
--- a/lang/python/gpgme.i
+++ b/lang/python/gpgme.i
@@ -125,7 +125,8 @@
// Special handling for references to our objects.
%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
wrapperN, where N is $argnum. Here in this fragment, SWIG will
automatically append $argnum. */
@@ -138,6 +139,7 @@
&bytesio, &view);
if (pypointer == NULL)
return NULL;
+ have_view = !! view.obj;
/* 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 {
/* See whether we need to update the Python buffer. */
- if (resultobj && wrapper$argnum && view$argnum.buf
- && wrapper$argnum->data.mem.buffer != NULL)
+ if (resultobj && wrapper$argnum && view$argnum.buf)
{
- /* The buffer is dirty. */
- if (view$argnum.readonly)
+ int dirty;
+ char *new_data = NULL;
+ size_t new_size;
+
+#if HAVE_DATA_H
+ 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)
{
- Py_XDECREF(resultobj);
- resultobj = NULL;
- PyErr_SetString(PyExc_ValueError, "cannot update read-only buffer");
- }
-
- /* See if we need to truncate the buffer. */
- if (resultobj && view$argnum.len != wrapper$argnum->data.mem.length)
- {
- if (bytesio$argnum == NULL)
+ /* The buffer is dirty. */
+ if (view$argnum.readonly)
{
Py_XDECREF(resultobj);
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;
- PyBuffer_Release(&view$argnum);
- retval = PyObject_CallMethod(bytesio$argnum, "truncate", "l",
- (long)
- wrapper$argnum->data.mem.length);
- if (retval == NULL)
+ if (bytesio$argnum == NULL)
{
Py_XDECREF(resultobj);
resultobj = NULL;
+ PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
}
else
{
- Py_DECREF(retval);
-
- retval = PyObject_CallMethod(bytesio$argnum, "getbuffer", NULL);
- if (retval == NULL
- || PyObject_GetBuffer(retval, &view$argnum,
- PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
+ PyObject *retval;
+ PyBuffer_Release(&view$argnum);
+ assert(view$argnum.obj == NULL);
+ retval = PyObject_CallMethod(bytesio$argnum, "truncate",
+ "l", (long) new_size);
+ if (retval == NULL)
{
Py_XDECREF(resultobj);
resultobj = NULL;
}
-
- Py_XDECREF(retval);
-
- if (resultobj && view$argnum.len
- != wrapper$argnum->data.mem.length)
+ else
{
- Py_XDECREF(resultobj);
- resultobj = NULL;
- PyErr_Format(PyExc_ValueError,
- "Expected buffer of length %zu, got %zi",
- wrapper$argnum->data.mem.length,
- view$argnum.len);
+ Py_DECREF(retval);
+
+ retval = PyObject_CallMethod(bytesio$argnum,
+ "getbuffer", NULL);
+ if (retval == NULL
+ || 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 (resultobj)
- memcpy(view$argnum.buf, wrapper$argnum->data.mem.buffer,
- wrapper$argnum->data.mem.length);
+#if ! HAVE_DATA_H
+ free (new_data);
+#endif
}
/* Free the temporary wrapper, if any. */
if (wrapper$argnum)
gpgme_data_release(wrapper$argnum);
Py_XDECREF (bytesio$argnum);
- if (wrapper$argnum && view$argnum.buf)
+ if (have_view$argnum && view$argnum.buf)
PyBuffer_Release(&view$argnum);
}
@@ -398,7 +429,6 @@
SWIG. */
%{
#include <gpgme.h>
-#include "src/data.h" /* For struct gpgme_data. */
%}
/* This is for notations, where we want to hide the length fields, and
diff --git a/lang/python/helpers.c b/lang/python/helpers.c
index 43a55d08..d6cbb883 100644
--- a/lang/python/helpers.c
+++ b/lang/python/helpers.c
@@ -254,6 +254,7 @@ object_to_gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
if (data != input)
Py_DECREF(data);
+ assert (view->obj);
assert (view->ndim == 1);
assert (view->shape == NULL);
assert (view->strides == NULL);