diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i index dfa3775c..bc957e57 100644 --- a/lang/python/gpgme.i +++ b/lang/python/gpgme.i @@ -36,11 +36,16 @@ /* 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 { @@ -50,19 +55,35 @@ 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 { @@ -83,7 +104,10 @@ } } %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. @@ -296,13 +320,22 @@ } /* 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 { @@ -320,7 +353,9 @@ $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; diff --git a/lang/python/helpers.c b/lang/python/helpers.c index 0b4a7736..6e63c97a 100644 --- a/lang/python/helpers.c +++ b/lang/python/helpers.c @@ -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);