python: Make type translation compatible with Python 2.7.
authorJustus Winter <justus@g10code.com>
Mon, 12 Sep 2016 15:11:19 +0000 (17:11 +0200)
committerJustus Winter <justus@g10code.com>
Mon, 12 Sep 2016 15:11:19 +0000 (17:11 +0200)
* lang/python/gpgme.i: Avoid functions not available in Python 2.7.
* lang/python/helpers.c: Likewise.

Signed-off-by: Justus Winter <justus@g10code.com>
lang/python/gpgme.i
lang/python/helpers.c

index dfa3775..bc957e5 100644 (file)
 
 
 /* Allow use of Unicode objects, bytes, and None for strings.  */
-%typemap(in) const char * {
+%typemap(in) const char *(PyObject *encodedInput = NULL) {
   if ($input == Py_None)
     $1 = NULL;
   else if (PyUnicode_Check($input))
-    $1 = PyUnicode_AsUTF8($input);
+    {
+      encodedInput = PyUnicode_AsUTF8String($input);
+      if (encodedInput == NULL)
+        return NULL;
+      $1 = PyBytes_AsString(encodedInput);
+    }
   else if (PyBytes_Check($input))
     $1 = PyBytes_AsString($input);
   else {
     return NULL;
   }
 }
-%typemap(freearg) const char * "";
+%typemap(freearg) const char * {
+  Py_XDECREF(encodedInput$argnum);
+}
 
 /* Likewise for a list of strings.  */
-%typemap(in) const char *[] (void *vector = NULL) {
+%typemap(in) const char *[] (void *vector = NULL,
+                             size_t size,
+                             PyObject **pyVector = NULL) {
   /* Check if is a list */
   if (PyList_Check($input)) {
-    size_t i, size = PyList_Size($input);
+    size_t i, j;
+    size = PyList_Size($input);
     $1 = (char **) (vector = malloc((size+1) * sizeof(char *)));
+    pyVector = calloc(sizeof *pyVector, size);
 
     for (i = 0; i < size; i++) {
       PyObject *o = PyList_GetItem($input,i);
       if (PyUnicode_Check(o))
-        $1[i] = PyUnicode_AsUTF8(o);
+        {
+          pyVector[i] = PyUnicode_AsUTF8String(o);
+          if (pyVector[i] == NULL)
+            {
+              free(vector);
+              for (j = 0; j < i; j++)
+                Py_XDECREF(pyVector[j]);
+              return NULL;
+            }
+          $1[i] = PyBytes_AsString(pyVector[i]);
+        }
       else if (PyString_Check(o))
        $1[i] = PyString_AsString(o);
       else {
   }
 }
 %typemap(freearg) const char *[] {
+  size_t i;
   free(vector$argnum);
+  for (i = 0; i < size$argnum; i++)
+    Py_XDECREF(pyVector$argnum[i]);
 }
 
 // Release returned buffers as necessary.
 }
 
 /* For gpgme_data_write, but should be universal.  */
-%typemap(in) (const void *buffer, size_t size) {
+%typemap(in) (const void *buffer, size_t size)(PyObject *encodedInput = NULL) {
   Py_ssize_t ssize;
 
   if ($input == Py_None)
     $1 = NULL, $2 = 0;
   else if (PyUnicode_Check($input))
-    $1 = PyUnicode_AsUTF8AndSize($input, &ssize);
+    {
+      encodedInput = PyUnicode_AsUTF8String($input);
+      if (encodedInput == NULL)
+        return NULL;
+      if (PyBytes_AsStringAndSize(encodedInput, (char **) &$1, &ssize) == -1)
+        {
+          Py_DECREF(encodedInput);
+          return NULL;
+        }
+    }
   else if (PyBytes_Check($input))
     PyBytes_AsStringAndSize($input, (char **) &$1, &ssize);
   else {
       $2 = (size_t) ssize;
     }
 }
-%typemap(freearg) (const void *buffer, size_t size) "";
+%typemap(freearg) (const void *buffer, size_t size) {
+  Py_XDECREF(encodedInput$argnum);
+}
 
 // Make types containing 'next' field to be lists
 %ignore next;
index 0b4a773..6e63c97 100644 (file)
@@ -191,14 +191,17 @@ _pyme_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
   pyname = PyObject_GetAttrString(input, "_ctype");
   if (pyname && PyUnicode_Check(pyname))
     {
-      if (strcmp(PyUnicode_AsUTF8(pyname), objtype) != 0)
+      PyObject *encoded = PyUnicode_AsUTF8String(pyname);
+      if (strcmp(PyBytes_AsString(encoded), objtype) != 0)
         {
           PyErr_Format(PyExc_TypeError,
                        "arg %d: Expected value of type %s, but got %s",
-                       argnum, objtype, PyUnicode_AsUTF8(pyname));
+                       argnum, objtype, PyBytes_AsString(encoded));
+          Py_DECREF(encoded);
           Py_DECREF(pyname);
           return NULL;
         }
+      Py_DECREF(encoded);
     }
   else
     return NULL;
@@ -334,6 +337,7 @@ static gpgme_error_t pyPassphraseCb(void *hook,
   PyObject *args = NULL;
   PyObject *retval = NULL;
   PyObject *dataarg = NULL;
+  PyObject *encoded = NULL;
   gpgme_error_t err_status = 0;
 
   _pyme_exception_init();
@@ -388,7 +392,17 @@ static gpgme_error_t pyPassphraseCb(void *hook,
       else if (PyUnicode_Check(retval))
         {
           Py_ssize_t ssize;
-          buf = PyUnicode_AsUTF8AndSize(retval, &ssize);
+          encoded = PyUnicode_AsUTF8String(retval);
+          if (encoded == NULL)
+            {
+              err_status = gpg_error(GPG_ERR_GENERAL);
+              goto leave;
+            }
+          if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
+            {
+              err_status = gpg_error(GPG_ERR_GENERAL);
+              goto leave;
+            }
           assert (! buf || ssize >= 0);
           len = (size_t) ssize;
         }
@@ -418,6 +432,7 @@ static gpgme_error_t pyPassphraseCb(void *hook,
   if (err_status)
     _pyme_stash_callback_exception(self);
 
+  Py_XDECREF(encoded);
   return err_status;
 }
 
@@ -676,10 +691,23 @@ gpgme_error_t _pyme_edit_cb(void *opaque, gpgme_status_code_t status,
     err_status = _pyme_exception2code();
   } else {
     if (fd>=0 && retval && PyUnicode_Check(retval)) {
+      PyObject *encoded = NULL;
       const char *buffer;
       Py_ssize_t size;
 
-      buffer = PyUnicode_AsUTF8AndSize(retval, &size);
+      encoded = PyUnicode_AsUTF8String(retval);
+      if (encoded == NULL)
+        {
+          err_status = gpg_error(GPG_ERR_GENERAL);
+          goto leave;
+        }
+      if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
+        {
+          Py_DECREF(encoded);
+          err_status = gpg_error(GPG_ERR_GENERAL);
+          goto leave;
+        }
+
       if (write(fd, buffer, size) < 0) {
         err_status = gpgme_error_from_syserror ();
         _pyme_raise_exception (err_status);
@@ -688,8 +716,10 @@ gpgme_error_t _pyme_edit_cb(void *opaque, gpgme_status_code_t status,
         err_status = gpgme_error_from_syserror ();
         _pyme_raise_exception (err_status);
       }
+      Py_DECREF(encoded);
     }
   }
+ leave:
   if (err_status)
     _pyme_stash_callback_exception(self);