diff --git a/.gitignore b/.gitignore index 1a4bbf5..8719ece 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ /gpgme-1.13.1.tar.bz2 /gpgme-1.14.0.tar.bz2 /gpgme-1.15.1.tar.bz2 +/gpgme-1.15.1.licenses.tar.bz2 diff --git a/gpgme-1.15.1-covscan.patch b/gpgme-1.15.1-covscan.patch new file mode 100644 index 0000000..216786f --- /dev/null +++ b/gpgme-1.15.1-covscan.patch @@ -0,0 +1,377 @@ +From 3101e381eb7ff31138aa20438ae757365e390d2c Mon Sep 17 00:00:00 2001 +From: Jiri Kucera +Date: Thu, 15 Jul 2021 22:41:37 +0200 +Subject: [PATCH] lang/python/gpgme.i: Fix memleaks + +--- + lang/python/gpgme.i | 85 +++++++++++++++++++++++++++------------------ + 1 file changed, 52 insertions(+), 33 deletions(-) + +diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i +index 87371af8..fabf9e2c 100644 +--- a/lang/python/gpgme.i ++++ b/lang/python/gpgme.i +@@ -53,7 +53,7 @@ + { + encodedInput = PyUnicode_AsUTF8String($input); + if (encodedInput == NULL) +- return NULL; ++ SWIG_fail; + $1 = PyBytes_AsString(encodedInput); + } + else if (PyBytes_Check($input)) +@@ -62,7 +62,7 @@ + PyErr_Format(PyExc_TypeError, + "arg %d: expected str, bytes, or None, got %s", + $argnum, $input->ob_type->tp_name); +- return NULL; ++ SWIG_fail; + } + } + %typemap(freearg) const char * { +@@ -70,14 +70,16 @@ + } + + /* Likewise for a list of strings. */ +-%typemap(in) const char *[] (void *vector = NULL, +- size_t size, ++%typemap(arginit) const char *[] { ++ $1 = NULL; ++} ++%typemap(in) const char *[] (size_t size, + PyObject **pyVector = NULL) { + /* Check if is a list */ + if (PyList_Check($input)) { + size_t i, j; + size = PyList_Size($input); +- $1 = (char **) (vector = malloc((size+1) * sizeof(char *))); ++ $1 = (char **) malloc((size+1) * sizeof(char *)); + pyVector = calloc(sizeof *pyVector, size); + + for (i = 0; i < size; i++) { +@@ -86,12 +88,7 @@ + { + pyVector[i] = PyUnicode_AsUTF8String(o); + if (pyVector[i] == NULL) +- { +- free(vector); +- for (j = 0; j < i; j++) +- Py_XDECREF(pyVector[j]); +- return NULL; +- } ++ SWIG_fail; + $1[i] = PyBytes_AsString(pyVector[i]); + } + else if (PyString_Check(o)) +@@ -101,8 +98,7 @@ + "arg %d: list must contain only str or bytes, got %s " + "at position %d", + $argnum, o->ob_type->tp_name, i); +- free($1); +- return NULL; ++ SWIG_fail; + } + } + $1[i] = NULL; +@@ -110,14 +106,17 @@ + PyErr_Format(PyExc_TypeError, + "arg %d: expected a list of str or bytes, got %s", + $argnum, $input->ob_type->tp_name); +- return NULL; ++ SWIG_fail; + } + } + %typemap(freearg) const char *[] { +- size_t i; +- free(vector$argnum); +- for (i = 0; i < size$argnum; i++) +- Py_XDECREF(pyVector$argnum[i]); ++ if (pyVector$argnum) { ++ size_t i; ++ for (i = 0; i < size$argnum; i++) ++ Py_XDECREF(pyVector$argnum[i]); ++ free(pyVector$argnum); ++ } ++ if ($1) free($1); + } + + /* Release returned buffers as necessary. */ +@@ -135,7 +134,7 @@ + if (!PySequence_Check($input)) { + PyErr_Format(PyExc_ValueError, "arg %d: Expected a list of gpgme_key_t", + $argnum); +- return NULL; ++ SWIG_fail; + } + if((numb = PySequence_Length($input)) != 0) { + $1 = (gpgme_key_t*)malloc((numb+1)*sizeof(gpgme_key_t)); +@@ -152,8 +151,7 @@ + "arg %d: list must contain only gpgme_key_ts, got %s " + "at position %d", + $argnum, pypointer->ob_type->tp_name, i); +- free($1); +- return NULL; ++ SWIG_fail; + } + Py_DECREF(pypointer); + } +@@ -179,7 +177,7 @@ + pypointer = _gpg_obj2gpgme_data_t($input, $argnum, &wrapper, + &bytesio, &view); + if (pypointer == NULL) +- return NULL; ++ SWIG_fail; + have_view = !! view.obj; + + /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */ +@@ -189,7 +187,7 @@ + if ((SWIG_ConvertPtr(pypointer,(void **) &$1, $1_descriptor, + SWIG_POINTER_EXCEPTION | $disown )) == -1) { + Py_DECREF(pypointer); +- return NULL; ++ SWIG_fail; + } + Py_DECREF(pypointer); + } +@@ -347,6 +345,10 @@ + } + + /* Those are for gpgme_data_read() and gpgme_strerror_r(). */ ++%typemap(arginit) (void *buffer, size_t size), (char *buf, size_t buflen) { ++ $1 = NULL; ++ $2 = 0; ++} + %typemap(in) (void *buffer, size_t size), (char *buf, size_t buflen) { + { + long tmp$argnum; +@@ -359,12 +361,12 @@ + else + { + PyErr_SetString(PyExc_TypeError, "Numeric argument expected"); +- return NULL; ++ SWIG_fail; + } + + if (tmp$argnum < 0) { + PyErr_SetString(PyExc_ValueError, "Positive integer expected"); +- return NULL; ++ SWIG_fail; + } + $2 = (size_t) tmp$argnum; + $1 = ($1_ltype) malloc($2+1); +@@ -373,11 +375,11 @@ + %typemap(argout) (void *buffer, size_t size), (char *buf, size_t buflen) { + Py_XDECREF($result); /* Blow away any previous result */ + if (result < 0) { /* Check for I/O error */ +- free($1); ++ if ($1) free($1); + return PyErr_SetFromErrno(PyExc_RuntimeError); + } + $result = PyBytes_FromStringAndSize($1,result); +- free($1); ++ if ($1) free($1); + } + + /* For gpgme_data_write, but should be universal. */ +@@ -390,11 +392,11 @@ + { + encodedInput = PyUnicode_AsUTF8String($input); + if (encodedInput == NULL) +- return NULL; ++ SWIG_fail; + if (PyBytes_AsStringAndSize(encodedInput, (char **) &$1, &ssize) == -1) + { + Py_DECREF(encodedInput); +- return NULL; ++ SWIG_fail; + } + } + else if (PyBytes_Check($input)) +@@ -403,7 +405,7 @@ + PyErr_Format(PyExc_TypeError, + "arg %d: expected str, bytes, or None, got %s", + $argnum, $input->ob_type->tp_name); +- return NULL; ++ SWIG_fail; + } + + if (! $1) +@@ -432,8 +434,17 @@ + size++; + } + $result = PyList_New(size); ++ if ($result == NULL) ++ SWIG_fail; + for (i=0,curr=$1; inext) { + PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, %newpointer_flags); ++ if (o == NULL) { ++ int j; ++ for (j = 0; j < i; j++) ++ Py_XDECREF(PyList_GetItem($result, j)); ++ Py_DECREF($result); ++ SWIG_fail; ++ } + PyList_SetItem($result, i, o); + } + } +@@ -446,6 +457,8 @@ + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); ++ if (fragile == NULL) ++ SWIG_fail; + $result = _gpg_wrap_result(fragile, name); + Py_DECREF(fragile); + } +@@ -469,22 +482,28 @@ wrapresult(gpgme_vfs_mount_result_t, "VFSMountResult") + } + $result = PyList_New(size); + if ($result == NULL) +- return NULL; /* raise */ ++ SWIG_fail; /* raise */ + for (i=0,curr=$1; inext) { + PyObject *fragile, *o; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, + %newpointer_flags); + if (fragile == NULL) + { ++ int j; ++ for (j = 0; j < i; j++) ++ Py_XDECREF(PyList_GetItem($result, j)); + Py_DECREF($result); +- return NULL; /* raise */ ++ SWIG_fail; /* raise */ + } + o = _gpg_wrap_result(fragile, "EngineInfo"); + Py_DECREF(fragile); + if (o == NULL) + { ++ int j; ++ for (j = 0; j < i; j++) ++ Py_XDECREF(PyList_GetItem($result, j)); + Py_DECREF($result); +- return NULL; /* raise */ ++ SWIG_fail; /* raise */ + } + PyList_SetItem($result, i, o); + } + +From b2815dcba2e75f79a6349191b3744952a9bd3311 Mon Sep 17 00:00:00 2001 +From: Jiri Kucera +Date: Sat, 17 Jul 2021 01:12:08 +0200 +Subject: [PATCH] lang/cpp/src/data.cpp: Fix memleaks + +--- + lang/cpp/src/data.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lang/cpp/src/data.cpp b/lang/cpp/src/data.cpp +index 7a93cbc2..d08a29db 100644 +--- a/lang/cpp/src/data.cpp ++++ b/lang/cpp/src/data.cpp +@@ -249,6 +249,7 @@ std::vector GpgME::Data::toKeys(Protocol proto) const + } + + if (gpgme_op_keylist_from_data_start (ctx->impl()->ctx, d->data, 0)) { ++ delete ctx; + return ret; + } + + +From eb3bf52fcb437b0508b2912f648ac25799daef55 Mon Sep 17 00:00:00 2001 +From: Jiri Kucera +Date: Sat, 17 Jul 2021 01:12:45 +0200 +Subject: [PATCH] src/engine-gpg.c: Fix memleaks + +--- + src/engine-gpg.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/src/engine-gpg.c b/src/engine-gpg.c +index b51ea173..af74714c 100644 +--- a/src/engine-gpg.c ++++ b/src/engine-gpg.c +@@ -1148,6 +1148,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname) + to avoid and given that we reach this here only + after a malloc failure for a small object, it is + probably better not to do anything. */ ++ free_argv (argv); + return gpg_error (GPG_ERR_GENERAL); + } + /* If the data_type is FD, we have to do a dup2 here. */ +@@ -1270,6 +1271,9 @@ read_status (engine_gpg_t gpg) + buffer = realloc (buffer, bufsize); + if (!buffer) + return gpg_error_from_syserror (); ++ /* Update buffer and bufsize here to prevent memory leaks. */ ++ gpg->status.buffer = buffer; ++ gpg->status.bufsize = bufsize; + } + + nread = _gpgme_io_read (gpg->status.fd[0], +@@ -1382,8 +1386,6 @@ read_status (engine_gpg_t gpg) + } + + /* Update the gpg object. */ +- gpg->status.bufsize = bufsize; +- gpg->status.buffer = buffer; + gpg->status.readpos = readpos; + return 0; + } +@@ -1423,6 +1425,9 @@ read_colon_line (engine_gpg_t gpg) + buffer = realloc (buffer, bufsize); + if (!buffer) + return gpg_error_from_syserror (); ++ /* Prevent memory leaks. */ ++ gpg->colon.bufsize = bufsize; ++ gpg->colon.buffer = buffer; + } + + nread = _gpgme_io_read (gpg->colon.fd[0], buffer+readpos, bufsize-readpos); +@@ -1502,8 +1507,6 @@ read_colon_line (engine_gpg_t gpg) + } + + /* Update the gpg object. */ +- gpg->colon.bufsize = bufsize; +- gpg->colon.buffer = buffer; + gpg->colon.readpos = readpos; + return 0; + } + +From e94363045f104fe57188bd014c91462e3693ec24 Mon Sep 17 00:00:00 2001 +From: Jiri Kucera +Date: Sat, 17 Jul 2021 01:14:14 +0200 +Subject: [PATCH] src/engine-gpgsm.c: Fix memleaks + +--- + src/engine-gpgsm.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c +index d5f0d7a9..7a8a049b 100644 +--- a/src/engine-gpgsm.c ++++ b/src/engine-gpgsm.c +@@ -1533,8 +1533,10 @@ gpgsm_export (void *engine, const char *pattern, gpgme_export_mode_t mode, + gpgsm->output_cb.data = keydata; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" + : map_data_enc (gpgsm->output_cb.data)); +- if (err) ++ if (err) { ++ free (cmd); + return err; ++ } + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; +@@ -1634,8 +1636,10 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode, + gpgsm->output_cb.data = keydata; + err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor" + : map_data_enc (gpgsm->output_cb.data)); +- if (err) ++ if (err) { ++ free (line); + return err; ++ } + gpgsm_clear_fd (gpgsm, INPUT_FD); + gpgsm_clear_fd (gpgsm, MESSAGE_FD); + gpgsm->inline_data = NULL; diff --git a/gpgme-1.15.1-glibc-closefrom.patch b/gpgme-1.15.1-glibc-closefrom.patch new file mode 100644 index 0000000..4c1e11f --- /dev/null +++ b/gpgme-1.15.1-glibc-closefrom.patch @@ -0,0 +1,13 @@ +diff --git a/src/posix-io.c b/src/posix-io.c +index e712ef2..2a3a81f 100644 +--- a/src/posix-io.c ++++ b/src/posix-io.c +@@ -570,7 +570,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, + if (fd_list[i].fd > fd) + fd = fd_list[i].fd; + fd++; +-#if defined(__sun) || defined(__FreeBSD__) ++#if defined(__sun) || defined(__FreeBSD__) || defined(__GLIBC__) + closefrom (fd); + max_fds = fd; + #else /*!__sun */ diff --git a/gpgme.spec b/gpgme.spec index 6708ffc..4d186d9 100644 --- a/gpgme.spec +++ b/gpgme.spec @@ -9,11 +9,17 @@ Name: gpgme Summary: GnuPG Made Easy - high level crypto API Version: 1.15.1 -Release: 3%{?dist} +Release: 4%{?dist} -License: LGPLv2+ +# /usr/bin/gpgme-tool is licensed under GPLv3+ +# the rest is licensed under LGPLv2+ +# Note: /usr/bin/gpgme-json contains bits of MIT licensed code, but its +# effective license remains LGPLv2+ +# (see https://fedoraproject.org/wiki/Licensing:FAQ) +License: LGPLv2+ and GPLv3+ URL: https://gnupg.org/related_software/gpgme/ -Source0: https://gnupg.org/ftp/gcrypt/gpgme/gpgme-%{version}.tar.bz2 +#Source0: https://gnupg.org/ftp/gcrypt/gpgme/gpgme-%%{version}.tar.bz2 +Source0: gpgme-%{version}.licenses.tar.bz2 Source2: gpgme-multilib.h ## downstream patches @@ -23,6 +29,10 @@ Patch1001: 0001-don-t-add-extra-libraries-for-linking.patch Patch1002: gpgme-1.3.2-largefile.patch # Let's fix stupid AX_PYTHON_DEVEL Patch1003: 0001-fix-stupid-ax_python_devel.patch +# Fix static analysis issues +Patch1004: gpgme-1.15.1-covscan.patch +# glibc 2.34 introduces closefrom() +Patch1005: gpgme-1.15.1-glibc-closefrom.patch #BuildRequires: autoconf #BuildRequires: automake @@ -155,6 +165,7 @@ mv %{buildroot}%{_includedir}/gpgme.h \ install -m644 -p -D %{SOURCE2} %{buildroot}%{_includedir}/gpgme.h %endif chrpath -d %{buildroot}%{_bindir}/%{name}-tool +chrpath -d %{buildroot}%{_bindir}/%{name}-json chrpath -d %{buildroot}%{_libdir}/lib%{name}pp.so* chrpath -d %{buildroot}%{_libdir}/libq%{name}.so* @@ -168,7 +179,7 @@ make check %endif %files -%license COPYING* +%license COPYING* LICENSES %doc AUTHORS NEWS README* %{_bindir}/%{name}-json %{_libdir}/lib%{name}.so.11* @@ -211,6 +222,10 @@ make check %{python3_sitearch}/gpg/ %changelog +* Fri Jul 16 2021 Jiri Kucera - 1.15.1-4 +- Fix license and covscan issues + Resolves: #1938732 + * Thu Apr 15 2021 Mohan Boddu - 1.15.1-3 - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 diff --git a/sources b/sources index 99b29fe..df6b47d 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (gpgme-1.15.1.tar.bz2) = 1d75a848cce6389f7cb8896b57a28dfe1dc5a447bfb4f128b0994a43e04134343400a3be063e971f03dfd595474cfd558519741d5d56afb3e84853ad4f2a45c2 +SHA512 (gpgme-1.15.1.licenses.tar.bz2) = beeddb53166b21db31904b42a94c0f01189c62df32370d920f52cdaac58d81bc299990c4653ae313a5d0dbb5785929ef95e3a42ca693a51b67de5caa2721fa16