commit:     c8bf4b933d88520d7a9ad6f856412e62772f044f
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Jan 19 16:31:23 2020 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Jan 19 16:31:23 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c8bf4b93

libq/tree: fix Coverity 206560 Resource leak

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 libq/tree.c | 52 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/libq/tree.c b/libq/tree.c
index 94f9665..2efdb7c 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -138,8 +138,12 @@ tree_open_binpkg(const char *sroot, const char *spkg)
                ret->cachetype = CACHE_BINPKGS;
 
                snprintf(buf, sizeof(buf), "%s%s/%s", sroot, spkg, 
binpkg_packages);
-               if (eat_file(buf, &ret->pkgs, &ret->pkgslen))
+               if (eat_file(buf, &ret->pkgs, &ret->pkgslen)) {
                        ret->cachetype = CACHE_PACKAGES;
+               } else if (ret->pkgs != NULL) {
+                       free(ret->pkgs);
+                       ret->pkgs = NULL;
+               }
        }
 
        return ret;
@@ -1237,10 +1241,12 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb 
callback, void *priv)
 
        /* reused for every entry */
        tree_cat_ctx *cat = NULL;
-       tree_pkg_ctx *pkg = xzalloc(sizeof(tree_pkg_ctx));
-       tree_pkg_meta *meta = xzalloc(sizeof(tree_pkg_meta));
+       tree_pkg_ctx pkg;
+       tree_pkg_meta meta;
        depend_atom *atom = NULL;
 
+       memset(&meta, 0, sizeof(meta));
+
        do {
                /* find next line */
                c = NULL;
@@ -1257,32 +1263,41 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb 
callback, void *priv)
                        if (atom != NULL) {
                                size_t pkgnamelen;
 
+                               memset(&pkg, 0, sizeof(pkg));
+
                                /* store meta ptr in repo->pkgs, such that 
get_pkg_meta
                                 * can grab it from there (for free) */
-                               ctx->pkgs = (char *)meta;
+                               c = ctx->pkgs;
+                               ctx->pkgs = (char *)&meta;
 
                                if (cat == NULL || strcmp(cat->name, 
atom->CATEGORY) != 0)
                                {
-                                       if (cat != NULL)
+                                       if (cat != NULL) {
+                                               atom_implode((depend_atom 
*)cat->pkg_ctxs);
+                                               cat->pkg_ctxs = NULL;
                                                tree_close_cat(cat);
-                                       pkg->cat_ctx = cat = tree_open_cat(ctx, 
atom->CATEGORY);
+                                       }
+                                       pkg.cat_ctx = cat = tree_open_cat(ctx, 
atom->CATEGORY);
+                                       cat->pkg_ctxs = (tree_pkg_ctx **)atom;  
/* for name */
                                }
                                pkgnamelen = snprintf(pkgname, sizeof(pkgname),
                                                "%s.tbz2", atom->PF);
                                pkgname[pkgnamelen - (sizeof(".tbz2") - 1)] = 
'\0';
-                               pkg->name = pkgname;
-                               pkg->slot = meta->Q_SLOT == NULL ? (char *)"0" 
: meta->Q_SLOT;
-                               pkg->repo = ctx->repo;
-                               pkg->atom = atom;
-                               pkg->fd = 0;  /* intentional, meta has already 
been read */
+                               pkg.name = pkgname;
+                               pkg.slot = meta.Q_SLOT == NULL ? (char *)"0" : 
meta.Q_SLOT;
+                               pkg.repo = ctx->repo;
+                               pkg.atom = atom;
+                               pkg.fd = 0;  /* intentional, meta has already 
been read */
 
                                /* do call callback with pkg_atom (populate cat 
and pkg) */
-                               ret |= callback(pkg, priv);
+                               ret |= callback(&pkg, priv);
 
-                               atom_implode(atom);
+                               ctx->pkgs = c;
+                               if (atom != (depend_atom *)cat->pkg_ctxs)
+                                       atom_implode(atom);
                        }
 
-                       memset(meta, 0, sizeof(meta[0]));
+                       memset(&meta, 0, sizeof(meta));
                        atom = NULL;
                        if (len > 0) {  /* hop over \n */
                                p++;
@@ -1318,7 +1333,7 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb 
callback, void *priv)
 #define match_key(X) match_key2(X,X)
 #define match_key2(X,Y) \
                } else if (strcmp(p, #X) == 0) { \
-                       meta->Q_##Y = c
+                       meta.Q_##Y = c
                match_key(DEFINED_PHASES);
                match_key(DEPEND);
                match_key2(DESC, DESCRIPTION);
@@ -1339,8 +1354,15 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb 
callback, void *priv)
                p = q;
        } while (len > 0);
 
+       if (cat != NULL) {
+               atom_implode((depend_atom *)cat->pkg_ctxs);
+               cat->pkg_ctxs = NULL;
+               tree_close_cat(cat);
+       }
+
        /* ensure we don't free a garbage pointer */
        ctx->repo = NULL;
+       ctx->do_sort = false;
 
        return ret;
 }

Reply via email to