On 4/15/25 13:48, Alexander Kuznetsov wrote:
path is allocated by asprintf() and must be freed later if realloc()
fails
Restructure the code to allocate path only after realloc() succeeds,
avoiding the need for an extra free()
Found by Linux Verification Center (
linuxtesting.org) with Svace.
Reported-by: Dmitry Fedin <d.fedin(a)fobos-nt.ru>
Signed-off-by: Alexander Kuznetsov <kuznetsovam(a)altlinux.org>
---
tools/nss/libvirt_nss.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/nss/libvirt_nss.c b/tools/nss/libvirt_nss.c
index d79a00a1b0..a1f33ee27b 100644
--- a/tools/nss/libvirt_nss.c
+++ b/tools/nss/libvirt_nss.c
@@ -137,12 +137,13 @@ findLease(const char *name,
if (dlen >= 7 && !strcmp(entry->d_name + dlen - 7,
".status")) {
char **tmpLease;
- if (asprintf(&path, "%s/%s", leaseDir, entry->d_name) <
0)
- goto cleanup;
-
tmpLease = realloc(leaseFiles, sizeof(char *) * (nleaseFiles + 1));
if (!tmpLease)
goto cleanup;
+
+ if (asprintf(&path, "%s/%s", leaseDir, entry->d_name) <
0)
+ goto cleanup;
+
Almost. Consider this is the first iteration of the while() loop. When
the control enters the while loop, leaseFiles is still set to NULL (due
to being initialized that way). realloc() succeeds and thus tmpLease
contains now a pointer to allocated memory. But then, if asprintf()
fails, the control jumps onto the cleanup label, where free(leaseFiles)
is called, but ...
leaseFiles = tmpLease;
... this ^^ was never executed. Thus there's still a memleak except this
time a different one.
leaseFiles[nleaseFiles++] = path;
#if defined(LIBVIRT_NSS_GUEST)
What we really need is:
tmpLease = realloc(leaseFiles, ...);
if (!tmpLease) goto cleanup;
leaseFiles = tmpLease;
if (asprintf(&path, ...) < 0) goto cleanup;
leaseFiles[nleaseFiles++] = path;
I'm changing your patch accordingly and merging.
Reviewed-by: Michal Privoznik <mprivozn(a)redhat.com>
Michal