Fix issues detected by static analyzers

Resolves: rhbz#1938793
This commit is contained in:
Pavla Kratochvilova 2021-07-27 14:18:21 +02:00
parent bea6623cfa
commit a4f49babd8
4 changed files with 358 additions and 1 deletions

View File

@ -0,0 +1,42 @@
From 71c6b26096086926f48d8fced1a03ca52a1eb745 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
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

View File

@ -0,0 +1,279 @@
From 6864aeffb0fa091dd2be1be339257825d7e80c54 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
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 <jrohel@redhat.com>
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 <jrohel@redhat.com>
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);
}

View File

@ -0,0 +1,30 @@
From 8615575144e6fd3d708a30983ed2415db479ef4c Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
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

View File

@ -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 <pkratoch@redhat.com> - 0.7.17-6
- Fix issues detected by static analyzers
* Tue Jun 22 2021 Mohan Boddu <mboddu@redhat.com> - 0.7.17-5
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065