diff --git a/0001-Fix-memory-leaks.patch b/0001-Fix-memory-leaks.patch new file mode 100644 index 0000000..af42f47 --- /dev/null +++ b/0001-Fix-memory-leaks.patch @@ -0,0 +1,42 @@ +From 71c6b26096086926f48d8fced1a03ca52a1eb745 Mon Sep 17 00:00:00 2001 +From: Jaroslav Rohel +Date: Mon, 29 Mar 2021 12:46:31 +0200 +Subject: [PATCH] Fix memory leaks + +--- + ext/repo_deb.c | 1 + + ext/testcase.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/ext/repo_deb.c b/ext/repo_deb.c +index 8f63756..34f40fa 100644 +--- a/ext/repo_deb.c ++++ b/ext/repo_deb.c +@@ -792,5 +792,6 @@ pool_deb_get_autoinstalled(Pool *pool, FILE *fp, Queue *q, int flags) + break; + } + } ++ solv_free(buf); + } + +diff --git a/ext/testcase.c b/ext/testcase.c +index 8fb6d79..4e9e315 100644 +--- a/ext/testcase.c ++++ b/ext/testcase.c +@@ -1477,11 +1477,11 @@ testcase_solverresult(Solver *solv, int resultflags) + queue_init(&q); + for (rid = 1; (rclass = solver_ruleclass(solv, rid)) != SOLVER_RULE_UNKNOWN; rid++) + { +- char *prefix = solv_dupjoin("rule ", testcase_rclass2str(rclass), " "); +- prefix = solv_dupappend(prefix, testcase_ruleid(solv, rid), 0); + solver_ruleliterals(solv, rid, &q); + if (rclass == SOLVER_RULE_FEATURE && q.count == 1 && q.elements[0] == -SYSTEMSOLVABLE) + continue; ++ char *prefix = solv_dupjoin("rule ", testcase_rclass2str(rclass), " "); ++ prefix = solv_dupappend(prefix, testcase_ruleid(solv, rid), 0); + for (i = 0; i < q.count; i++) + { + Id p = q.elements[i]; +-- +libgit2 1.0.1 + diff --git a/0002-Fix-lzopen-zstdopen-zchunkopen.patch b/0002-Fix-lzopen-zstdopen-zchunkopen.patch new file mode 100644 index 0000000..698f13d --- /dev/null +++ b/0002-Fix-lzopen-zstdopen-zchunkopen.patch @@ -0,0 +1,279 @@ +From 6864aeffb0fa091dd2be1be339257825d7e80c54 Mon Sep 17 00:00:00 2001 +From: Jaroslav Rohel +Date: Tue, 6 Apr 2021 09:17:27 +0200 +Subject: [PATCH 1/3] Fix: Use "solv_free" for memory allocated by + "solv_calloc" + +--- + ext/solv_xfopen.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c +index b3136cbb..a5de9e62 100644 +--- a/ext/solv_xfopen.c ++++ b/ext/solv_xfopen.c +@@ -199,7 +199,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz) + if (ret != LZMA_OK) + { + fclose(fp); +- free(lzfile); ++ solv_free(lzfile); + return 0; + } + return lzfile; +@@ -232,7 +232,7 @@ static int lzclose(void *cookie) + } + lzma_end(&lzfile->strm); + rc = fclose(lzfile->file); +- free(lzfile); ++ solv_free(lzfile); + return rc; + } + +@@ -432,7 +432,7 @@ static int zstdclose(void *cookie) + ZSTD_freeDStream(zstdfile->dstream); + } + rc = fclose(zstdfile->file); +- free(zstdfile); ++ solv_free(zstdfile); + return rc; + } + + +From ee8b8b9d72b816950e411ed26063c3a000b396ed Mon Sep 17 00:00:00 2001 +From: Jaroslav Rohel +Date: Mon, 29 Mar 2021 17:16:54 +0200 +Subject: [PATCH 2/3] Fix: lzopen and zstdopen: don't close supplied fd + +In the case of failure of some functions, the `fp` file stream has been +closed. And the stream closed the associated supplied `fd` file descriptor. + +The caller then closed the closed descriptor again (eg `curlfopen` in +`repoinfo_download.c`: `if (!Fp) close (fd);`) -> double_close. +In multithreaded software risk of race conditions. Another thread open +another file and reuse just closed file descriptor. The caller +then closes the file of another thread. +--- + ext/solv_xfopen.c | 45 ++++++++++++++++++++++++++------------------- + 1 file changed, 26 insertions(+), 19 deletions(-) + +diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c +index a5de9e62..4258fac1 100644 +--- a/ext/solv_xfopen.c ++++ b/ext/solv_xfopen.c +@@ -165,7 +165,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz) + LZFILE *lzfile; + lzma_ret ret; + +- if (!path && fd < 0) ++ if ((!path && fd < 0) || (path && fd >= 0)) + return 0; + for (; *mode; mode++) + { +@@ -176,14 +176,7 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz) + else if (*mode >= '1' && *mode <= '9') + level = *mode - '0'; + } +- if (fd != -1) +- fp = fdopen(fd, encoding ? "w" : "r"); +- else +- fp = fopen(path, encoding ? "w" : "r"); +- if (!fp) +- return 0; + lzfile = solv_calloc(1, sizeof(*lzfile)); +- lzfile->file = fp; + lzfile->encoding = encoding; + lzfile->eof = 0; + lzfile->strm = stream_init; +@@ -198,10 +191,20 @@ static LZFILE *lzopen(const char *path, const char *mode, int fd, int isxz) + ret = lzma_auto_decoder(&lzfile->strm, 100 << 20, 0); + if (ret != LZMA_OK) + { +- fclose(fp); + solv_free(lzfile); + return 0; + } ++ if (!path) ++ fp = fdopen(fd, encoding ? "w" : "r"); ++ else ++ fp = fopen(path, encoding ? "w" : "r"); ++ if (!fp) ++ { ++ lzma_end(&lzfile->strm); ++ solv_free(lzfile); ++ return 0; ++ } ++ lzfile->file = fp; + return lzfile; + } + +@@ -346,7 +349,7 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd) + FILE *fp; + ZSTDFILE *zstdfile; + +- if (!path && fd < 0) ++ if ((!path && fd < 0) || (path && fd >= 0)) + return 0; + for (; *mode; mode++) + { +@@ -357,12 +360,6 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd) + else if (*mode >= '1' && *mode <= '9') + level = *mode - '0'; + } +- if (fd != -1) +- fp = fdopen(fd, encoding ? "w" : "r"); +- else +- fp = fopen(path, encoding ? "w" : "r"); +- if (!fp) +- return 0; + zstdfile = solv_calloc(1, sizeof(*zstdfile)); + zstdfile->encoding = encoding; + if (encoding) +@@ -372,14 +369,12 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd) + if (!zstdfile->cstream) + { + solv_free(zstdfile); +- fclose(fp); + return 0; + } + if (ZSTD_isError(ZSTD_initCStream(zstdfile->cstream, level))) + { + ZSTD_freeCStream(zstdfile->cstream); + solv_free(zstdfile); +- fclose(fp); + return 0; + } + zstdfile->out.dst = zstdfile->buf; +@@ -393,13 +388,25 @@ static ZSTDFILE *zstdopen(const char *path, const char *mode, int fd) + { + ZSTD_freeDStream(zstdfile->dstream); + solv_free(zstdfile); +- fclose(fp); + return 0; + } + zstdfile->in.src = zstdfile->buf; + zstdfile->in.pos = 0; + zstdfile->in.size = 0; + } ++ if (!path) ++ fp = fdopen(fd, encoding ? "w" : "r"); ++ else ++ fp = fopen(path, encoding ? "w" : "r"); ++ if (!fp) ++ { ++ if (encoding) ++ ZSTD_freeCStream(zstdfile->cstream); ++ else ++ ZSTD_freeDStream(zstdfile->dstream); ++ solv_free(zstdfile); ++ return 0; ++ } + zstdfile->file = fp; + return zstdfile; + } + +From 725778574dda14dfa646f9a3f97568b15cdcbb2e Mon Sep 17 00:00:00 2001 +From: Jaroslav Rohel +Date: Tue, 30 Mar 2021 08:42:31 +0200 +Subject: [PATCH 3/3] Fix: zchunkopen: resources leaks, don't close supplied fd + +System variant: +- resource leaks when `zck_init_read` or `zck_init_write` fails +- supplied fd will be closed if `zck_create` fails + +Libsolv limited zchunk implementation: +- resource leak when `strcmp(mode, "r") != 0` +- supplied fd will be closed if `solv_zchunk_open` fails (Fix is thread + unsafe. However the original version caused a double-close in the caller + function and was thread unsafe too.) +--- + ext/solv_xfopen.c | 44 ++++++++++++++++++++++++++++++++++---------- + 1 file changed, 34 insertions(+), 10 deletions(-) + +diff --git a/ext/solv_xfopen.c b/ext/solv_xfopen.c +index 4258fac1..7dca41f0 100644 +--- a/ext/solv_xfopen.c ++++ b/ext/solv_xfopen.c +@@ -548,9 +548,9 @@ static void *zchunkopen(const char *path, const char *mode, int fd) + { + zckCtx *f; + +- if (!path && fd < 0) ++ if ((!path && fd < 0) || (path && fd >= 0)) + return 0; +- if (fd == -1) ++ if (path) + { + if (*mode != 'w') + fd = open(path, O_RDONLY); +@@ -562,18 +562,29 @@ static void *zchunkopen(const char *path, const char *mode, int fd) + f = zck_create(); + if (!f) + { +- close(fd); ++ if (path) ++ close(fd); + return 0; + } + if (*mode != 'w') + { + if(!zck_init_read(f, fd)) +- return 0; ++ { ++ zck_free(&f); ++ if (path) ++ close(fd); ++ return 0; ++ } + } + else + { + if(!zck_init_write(f, fd)) +- return 0; ++ { ++ zck_free(&f); ++ if (path) ++ close(fd); ++ return 0; ++ } + } + return cookieopen(f, mode, cookie_zckread, cookie_zckwrite, cookie_zckclose); + } +@@ -587,19 +598,32 @@ static void *zchunkopen(const char *path, const char *mode, int fd) + { + FILE *fp; + void *f; +- if (!path && fd < 0) ++ int tmpfd; ++ if ((!path && fd < 0) || (path && fd >= 0)) + return 0; +- if (fd != -1) ++ if (strcmp(mode, "r") != 0) ++ return 0; ++ if (!path) + fp = fdopen(fd, mode); + else + fp = fopen(path, mode); + if (!fp) + return 0; +- if (strcmp(mode, "r") != 0) +- return 0; + f = solv_zchunk_open(fp, 1); + if (!f) +- fclose(fp); ++ { ++ /* When 0 is returned, fd passed by user must not be closed! */ ++ /* Dup (save) the original fd to a temporary variable and then back. */ ++ /* It is ugly and thread unsafe hack (non atomical sequence fclose dup2). */ ++ if (!path) ++ tmpfd = dup(fd); ++ fclose(fp); ++ if (!path) ++ { ++ dup2(tmpfd, fd); ++ close(tmpfd); ++ } ++ } + return cookieopen(f, mode, (ssize_t (*)(void *, char *, size_t))solv_zchunk_read, 0, (int (*)(void *))solv_zchunk_close); + } + diff --git a/0003-Fix-Memory-leaks-in-SWIG-generated-code-for-Python.patch b/0003-Fix-Memory-leaks-in-SWIG-generated-code-for-Python.patch new file mode 100644 index 0000000..8753b85 --- /dev/null +++ b/0003-Fix-Memory-leaks-in-SWIG-generated-code-for-Python.patch @@ -0,0 +1,30 @@ +From 8615575144e6fd3d708a30983ed2415db479ef4c Mon Sep 17 00:00:00 2001 +From: Jaroslav Rohel +Date: Thu, 8 Apr 2021 12:17:09 +0200 +Subject: [PATCH] Fix: Memory leaks in SWIG generated code (for Python) + +There were memory leaks in the `Chksum_from_bin`, `Chksum_add`, +`SolvFp_write` functions wrapper for Python. + +The problem was in "freearg" typemap argument defined in "solv.i". +Therefore, the typemap was not applied. +--- + bindings/solv.i | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/bindings/solv.i b/bindings/solv.i +index 1882b13..3bbeca0 100644 +--- a/bindings/solv.i ++++ b/bindings/solv.i +@@ -63,7 +63,7 @@ typedef struct { + $2 = size; + } + +-%typemap(freearg,noblock=1,match="in") (const unsigned char *str, int len) { ++%typemap(freearg,noblock=1,match="in") (const unsigned char *str, size_t len) { + if (alloc$argnum == SWIG_NEWOBJ) %delete_array(buf$argnum); + } + +-- +libgit2 1.0.1 + diff --git a/libsolv.spec b/libsolv.spec index 53aa58f..8ab6a00 100644 --- a/libsolv.spec +++ b/libsolv.spec @@ -22,12 +22,15 @@ Name: lib%{libname} Version: 0.7.17 -Release: 5%{?dist} +Release: 6%{?dist} Summary: Package dependency solver License: BSD URL: https://github.com/openSUSE/libsolv Source: %{url}/archive/%{version}/%{name}-%{version}.tar.gz +Patch1: 0001-Fix-memory-leaks.patch +Patch2: 0002-Fix-lzopen-zstdopen-zchunkopen.patch +Patch3: 0003-Fix-Memory-leaks-in-SWIG-generated-code-for-Python.patch BuildRequires: cmake BuildRequires: gcc-c++ @@ -247,6 +250,9 @@ export LD_LIBRARY_PATH=%{buildroot}%{_libdir} %endif %changelog +* Tue Jul 27 2021 Pavla Kratochvilova - 0.7.17-6 +- Fix issues detected by static analyzers + * Tue Jun 22 2021 Mohan Boddu - 0.7.17-5 - Rebuilt for RHEL 9 BETA for openssl 3.0 Related: rhbz#1971065