commit:     d1442dee24b0760665a103c5c1b3ad838eef02f9
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Nov 30 16:25:18 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Nov 30 16:26:43 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=d1442dee

misc fixes for valgrind

mainly memory and socket leaks, sometimes using invalid data, this is
related to bug #701402

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

 libq/atom.c         |  5 +++++
 main.c              | 58 +++++++++++++++++++++++++++++++++++++++--------------
 q.c                 |  4 ++--
 qatom.c             |  2 +-
 qdepends.c          | 14 +++++++++----
 qlop.c              | 39 ++++++++++++++++++++++++++++++++++-
 qmanifest.c         | 49 ++++++++++++++++++++++++++++++--------------
 qmerge.c            | 11 ++++++++--
 tests/qmerge/dotest | 25 +++++++++++++----------
 tests/quse/dotest   |  4 ++++
 10 files changed, 160 insertions(+), 51 deletions(-)

diff --git a/libq/atom.c b/libq/atom.c
index 6e12c0a..efd32d1 100644
--- a/libq/atom.c
+++ b/libq/atom.c
@@ -335,6 +335,11 @@ atom_implode(depend_atom *atom)
 {
        if (!atom)
                errf("Atom is empty !");
+       while (atom->usedeps != NULL) {
+               atom_usedep *n = atom->usedeps->next;
+               free(atom->usedeps);
+               atom->usedeps = n;
+       }
        free(atom->suffixes);
        free(atom);
 }

diff --git a/main.c b/main.c
index ba15c8c..d6bbacf 100644
--- a/main.c
+++ b/main.c
@@ -224,8 +224,6 @@ makeargv(const char *string, int *argc, char ***argv)
 
        *argc = 1;
        (*argv)[0] = xstrdup(argv0);
-       q = xstrdup(string);
-       str = q;
 
        /* shortcut empty strings */
        while (isspace((int)*string))
@@ -233,6 +231,9 @@ makeargv(const char *string, int *argc, char ***argv)
        if (*string == '\0')
                return;
 
+       q = xstrdup(string);
+       str = q;
+
        remove_extra_space(str);
        rmspace(str);
 
@@ -744,18 +745,44 @@ initialize_portage_env(void)
        snprintf(pathbuf, sizeof(pathbuf), "%.*s", (int)i, configroot);
        read_repos_conf(pathbuf, "/usr/share/portage/config/repos.conf");
        read_repos_conf(pathbuf, "/etc/portage/repos.conf");
-       if (orig_main_overlay != main_overlay)
-               free(orig_main_overlay);
-       if (array_cnt(overlays) == 0) {
-               xarraypush_ptr(overlays, main_overlay);
-               xarraypush_str(overlay_names, "<PORTDIR>");
-               xarraypush_str(overlay_src, STR_DEFAULT);
-       } else if (orig_main_overlay == main_overlay) {
-               /* if no explicit overlay was flagged as main, take the first 
one */
+       /* special handling of PORTDIR envvar, else it comes too late, see
+        * also below where we handle the environment */
+       if ((s = getenv("PORTDIR")) != NULL) {
+               char *overlay;
+
+               array_for_each(overlays, i, overlay) {
+                       if (strcmp(overlay, s) == 0)
+                               break;
+                       overlay = NULL;
+               }
+               if (overlay == NULL) {
+                       main_overlay = xarraypush_str(overlays, s);
+                       xarraypush_str(overlay_names, "<PORTDIR>");
+                       xarraypush_str(overlay_src, "PORTDIR");
+               } else {
+                       free(array_get_elem(overlay_src, i));
+                       array_get_elem(overlay_src, i) = xstrdup("PORTDIR");
+                       main_overlay = overlay;
+               }
+               free(vars_to_read[11 /* PORTDIR */].src);
+               vars_to_read[11 /* PORTDIR */].src = xstrdup("PORTDIR");
+       }
+       if (orig_main_overlay != main_overlay) {
                free(orig_main_overlay);
-               main_overlay = array_get_elem(overlays, 0);
-               set_portage_env_var(&vars_to_read[11] /* PORTDIR */, 
main_overlay,
-                               (char *)array_get_elem(overlay_src, 0));
+       } else {
+               if (array_cnt(overlays) == 0) {
+                       xarraypush_ptr(overlays, main_overlay);
+                       xarraypush_str(overlay_names, "<PORTDIR>");
+                       xarraypush_str(overlay_src, STR_DEFAULT);
+               } else {
+                       /* if no explicit overlay was flagged as main, take the
+                        * first one */
+                       free(orig_main_overlay);
+                       main_overlay = array_get_elem(overlays, 0);
+                       free(vars_to_read[11 /* PORTDIR */].src);
+                       vars_to_read[11 /* PORTDIR */].src =
+                               xstrdup((char *)array_get_elem(overlay_src, 0));
+               }
        }
 
        /* consider Portage's defaults */
@@ -781,10 +808,11 @@ initialize_portage_env(void)
        read_portage_env_file(pathbuf, vars_to_read);
 
        /* finally, check the env */
-       for (i = 0; vars_to_read[i].name; ++i) {
+       for (i = 0; vars_to_read[i].name; i++) {
                var = &vars_to_read[i];
                s = getenv(var->name);
-               if (s != NULL)
+               /* PORTDIR was already added to overlays above, ignore it */
+               if (s != NULL && strcmp(var->name, "PORTDIR") != 0)
                        set_portage_env_var(var, s, var->name);
        }
 

diff --git a/q.c b/q.c
index 40cdc2a..a974df8 100644
--- a/q.c
+++ b/q.c
@@ -238,12 +238,12 @@ int q_main(int argc, char **argv)
 
                                switch (var->type) {
                                        case _Q_BOOL:
-                                               printf("%s%s%s\n",
+                                               printf("%s%s%s",
                                                                YELLOW, 
*var->value.b ? "1" : "0", NORM);
                                                break;
                                case _Q_STR:
                                case _Q_ISTR:
-                                               printf("%s%s%s\n", RED, 
*var->value.s, NORM);
+                                               printf("%s%s%s", RED, 
*var->value.s, NORM);
                                                break;
                                }
                                if (verbose)

diff --git a/qatom.c b/qatom.c
index 4ad6116..23d10d8 100644
--- a/qatom.c
+++ b/qatom.c
@@ -55,7 +55,7 @@ int qatom_main(int argc, char **argv)
        if (action == _COMPARE && (argc - optind) % 2)
                err("compare needs even number of arguments");
 
-       for (i = optind; i < argc; ++i) {
+       for (i = optind; i < argc; i++) {
                atom = atom_explode(argv[i]);
                if (atom == NULL) {
                        warnf("invalid atom: %s\n", argv[i]);

diff --git a/qdepends.c b/qdepends.c
index b5e8993..6f89835 100644
--- a/qdepends.c
+++ b/qdepends.c
@@ -345,17 +345,23 @@ int qdepends_main(int argc, char **argv)
                state.qmode &= ~QMODE_INSTALLED;
        }
 
-       if ((argc == optind) && !do_pretty)
+       if ((argc == optind) && !do_pretty) {
+               free_set(state.udeps);
                qdepends_usage(EXIT_FAILURE);
+       }
 
        if (do_pretty) {
+               ret = EXIT_SUCCESS;
                while (optind < argc) {
-                       if (!qdepends_print_depend(stdout, argv[optind++]))
-                               return EXIT_FAILURE;
+                       if (!qdepends_print_depend(stdout, argv[optind++])) {
+                               ret = EXIT_FAILURE;
+                               break;
+                       }
                        if (optind < argc)
                                fprintf(stdout, "\n");
                }
-               return EXIT_SUCCESS;
+               free_set(state.udeps);
+               return ret;
        }
 
        argc -= optind;

diff --git a/qlop.c b/qlop.c
index dcf1d47..d8e1d58 100644
--- a/qlop.c
+++ b/qlop.c
@@ -1014,6 +1014,42 @@ static int do_emerge_log(
                        printf("\n");
                }
        }
+
+       {
+               DECLARE_ARRAY(t);
+               values_set(merge_averages, t);
+               array_for_each(t, i, pkgw) {
+                       atom_implode(pkgw->atom);
+                       free(pkgw);
+               }
+               xarrayfree_int(t);
+               values_set(unmerge_averages, t);
+               array_for_each(t, i, pkgw) {
+                       atom_implode(pkgw->atom);
+                       free(pkgw);
+               }
+               xarrayfree_int(t);
+       }
+       free_set(merge_averages);
+       free_set(unmerge_averages);
+       array_for_each_rev(merge_matches, i, pkgw) {
+               atom_implode(pkgw->atom);
+               xarraydelete(merge_matches, i);
+       }
+       xarrayfree(merge_matches);
+       array_for_each_rev(unmerge_matches, i, pkgw) {
+               atom_implode(pkgw->atom);
+               xarraydelete(unmerge_matches, i);
+       }
+       xarrayfree(unmerge_matches);
+       if (atomset != NULL) {
+               DECLARE_ARRAY(t);
+               values_set(atomset, t);
+               array_for_each(t, i, atom)
+                       atom_implode(atom);
+               xarrayfree_int(t);
+               free_set(atomset);
+       }
        return 0;
 }
 
@@ -1073,7 +1109,8 @@ static array_t *probe_proc(array_t *atoms)
                                        rpath[rpathlen] = '\0';
                                        /* check if this points to a portage 
build:
                                         * 
<somepath>/portage/<cat>/<pf>/temp/build.log */
-                                       if (strcmp(rpath + rpathlen -
+                                       if (rpathlen > 
sizeof("/temp/build.log") &&
+                                                               strcmp(rpath + 
rpathlen -
                                                                
(sizeof("/temp/build.log") - 1),
                                                                
"/temp/build.log") == 0 &&
                                                        (p = strstr(rpath, 
"/portage/")) != NULL)

diff --git a/qmanifest.c b/qmanifest.c
index fee0151..c4c1322 100644
--- a/qmanifest.c
+++ b/qmanifest.c
@@ -752,6 +752,7 @@ process_dir_gen(void)
                gerr = gpgme_signers_add(gctx, gkey);
                if (gerr != GPG_ERR_NO_ERROR)
                        return "failed to add GPG key to sign list, is it a 
suitable key?";
+               gpgme_key_unref(gkey);
 
                gpg_pass = NULL;
                if (gpg_get_password) {
@@ -859,11 +860,6 @@ verify_gpg_sig(const char *path, verify_msg **msgs)
        struct tm *ctime;
        gpg_sig *ret = NULL;
 
-       if ((f = fopen(path, "r")) == NULL) {
-               msgs_add(msgs, path, NULL, "failed to open: %s", 
strerror(errno));
-               return NULL;
-       }
-
        if (gpgme_new(&g_ctx) != GPG_ERR_NO_ERROR) {
                msgs_add(msgs, path, NULL, "failed to create gpgme context");
                return NULL;
@@ -871,17 +867,32 @@ verify_gpg_sig(const char *path, verify_msg **msgs)
 
        if (gpgme_data_new(&out) != GPG_ERR_NO_ERROR) {
                msgs_add(msgs, path, NULL, "failed to create gpgme data");
+               gpgme_release(g_ctx);
+               return NULL;
+       }
+
+       if ((f = fopen(path, "r")) == NULL) {
+               msgs_add(msgs, path, NULL, "failed to open: %s", 
strerror(errno));
+               gpgme_data_release(out);
+               gpgme_release(g_ctx);
                return NULL;
        }
 
        if (gpgme_data_new_from_stream(&manifest, f) != GPG_ERR_NO_ERROR) {
                msgs_add(msgs, path, NULL,
                                "failed to create new gpgme data from stream");
+               gpgme_data_release(out);
+               gpgme_release(g_ctx);
+               fclose(f);
                return NULL;
        }
 
        if (gpgme_op_verify(g_ctx, manifest, NULL, out) != GPG_ERR_NO_ERROR) {
                msgs_add(msgs, path, NULL, "failed to verify signature");
+               gpgme_data_release(out);
+               gpgme_data_release(manifest);
+               gpgme_release(g_ctx);
+               fclose(f);
                return NULL;
        }
 
@@ -891,6 +902,9 @@ verify_gpg_sig(const char *path, verify_msg **msgs)
        if (vres == NULL || vres->signatures == NULL) {
                msgs_add(msgs, path, NULL,
                                "verification failed due to a missing gpg 
keyring");
+               gpgme_data_release(out);
+               gpgme_data_release(manifest);
+               gpgme_release(g_ctx);
                return NULL;
        }
 
@@ -971,6 +985,8 @@ verify_gpg_sig(const char *path, verify_msg **msgs)
                }
        }
 
+       gpgme_data_release(out);
+       gpgme_data_release(manifest);
        gpgme_release(g_ctx);
 
        return ret;
@@ -1529,8 +1545,10 @@ process_dir_vrfy(void)
        char *timestamp;
        verify_msg topmsg;
        verify_msg *walk = &topmsg;
+       verify_msg *next;
        gpg_sig *gs;
 
+       walk->next = NULL;
        gettimeofday(&startt, NULL);
 
        snprintf(buf, sizeof(buf), "metadata/layout.conf");
@@ -1581,10 +1599,12 @@ process_dir_vrfy(void)
         *   be there
         * - recurse into directories for which Manifest files are defined
         */
-       walk->next = NULL;
        if (verify_manifest(".\0", str_manifest, &walk) != 0)
                ret = "manifest verification failed";
 
+       gettimeofday(&finisht, NULL);
+
+       /* produce a report */
        {
                char *mfest;
                char *ebuild;
@@ -1593,7 +1613,6 @@ process_dir_vrfy(void)
                char *lastebuild = (char *)"-";
                char *msgline;
                const char *pfx;
-               verify_msg *next;
 
                for (walk = topmsg.next; walk != NULL; walk = walk->next) {
                        mfest = walk->msg;
@@ -1651,16 +1670,16 @@ process_dir_vrfy(void)
                                format_line(pfx, msg);
                        }
                }
-
-               walk = topmsg.next;
-               while (walk != NULL) {
-                       next = walk->next;
-                       free(walk);
-                       walk = next;
-               }
        }
 
-       gettimeofday(&finisht, NULL);
+       /* clean up messages */
+       walk = topmsg.next;
+       while (walk != NULL) {
+               next = walk->next;
+               free(walk->msg);
+               free(walk);
+               walk = next;
+       }
 
        etime = ((double)((finisht.tv_sec - startt.tv_sec) * 1000000 +
                                finisht.tv_usec) - (double)startt.tv_usec) / 
1000000.0;

diff --git a/qmerge.c b/qmerge.c
index c7b234e..5b7a298 100644
--- a/qmerge.c
+++ b/qmerge.c
@@ -481,6 +481,7 @@ install_mask_check_dir(
                        *npth = '\0';
                }
        }
+       scandir_free(files, cnt);
 }
 
 static void
@@ -620,6 +621,9 @@ install_mask_pwd(int iargc, char **iargv, const struct stat 
* const st, int fd)
                qpth[cnt] = '\0';
 
        install_mask_check_dir(masksv, masksc, st, fd, 1, INCLUDE, qpth);
+
+       free(masks);
+       free(masksv);
 }
 
 static char
@@ -917,11 +921,13 @@ merge_tree_at(int fd_src, const char *src, int fd_dst, 
const char *dst,
 
                        /* Make sure owner/mode is sane before we write out 
data */
                        if (fchown(fd_dstf, st.st_uid, st.st_gid)) {
-                               warnp("could not set ownership %s", cpath);
+                               warnp("could not set ownership (%zu/%zu) for 
%s",
+                                               (size_t)st.st_uid, 
(size_t)st.st_gid, cpath);
                                continue;
                        }
                        if (fchmod(fd_dstf, st.st_mode)) {
-                               warnp("could not set permission %s", cpath);
+                               warnp("could not set permission (%u) for %s",
+                                               (int)st.st_mode, cpath);
                                continue;
                        }
 
@@ -1439,6 +1445,7 @@ pkg_merge(int level, const depend_atom *atom, const 
struct pkg_t *pkg)
        printf("%s>>>%s %s%s%s/%s%s%s\n",
                        YELLOW, NORM, WHITE, atom->CATEGORY, NORM, CYAN, 
pkg->PF, NORM);
 
+       tree_close_cat(cat_ctx);
        tree_close(vdb);
 }
 

diff --git a/tests/qmerge/dotest b/tests/qmerge/dotest
index 86c6147..1563595 100755
--- a/tests/qmerge/dotest
+++ b/tests/qmerge/dotest
@@ -20,17 +20,20 @@ mkdir -p "${ROOT}/var/db/pkg"
 
 set +e
 
+# sanity check on environment
+q -Cev
+
 # Do a merge into an empty tree.
 
 out=$(yes | qmerge -F qmerge-test)
-tend $? "qmerge-test: [N] basic merge" || echo "${out}"
+tend $? "qmerge-test: [N] basic merge" || die "${out}"
 
 [[ ${out} != *"FAIL"* ]]
-tend $? "qmerge-test: [N] FAIL messages" || echo "${out}"
+tend $? "qmerge-test: [N] FAIL messages" || die "${out}"
 
 order=$(echo "${out}" | awk '$1 == ">>>" && $2 ~ /^pkg_/ { printf "%s ", $NF 
}')
 [[ ${order} == "pkg_pretend pkg_setup pkg_preinst pkg_postinst " ]]
-tend $? "qmerge-test: [N] pkg_* order of execution" || printf '%s\n' 
"${order}" "${out}"
+tend $? "qmerge-test: [N] pkg_* order of execution" || die "$(printf '%s\n' 
"${order}" "${out}")"
 
 ls -d "${ROOT}"/var/db/pkg/sys-devel/qmerge-test-* >/dev/null
 tend $? "qmerge-test: [N] vdb installed"
@@ -38,25 +41,25 @@ tend $? "qmerge-test: [N] vdb installed"
 [[ -x ${ROOT}/usr/bin/qmerge-test && \
    -f ${ROOT}/etc/some.conf && \
    -f ${ROOT}/etc/another.conf ]]
-tend $? "qmerge-test: [N] installed expected files" || treedir "${ROOT}"
+tend $? "qmerge-test: [N] installed expected files" || die "$(treedir 
"${ROOT}")"
 
 # Now do a re-emerge.
 
 out=$(yes | qmerge -F qmerge-test)
-tend $? "qmerge-test: [R] re-emerge" || echo "${out}"
+tend $? "qmerge-test: [R] re-emerge" || die "${out}"
 
 [[ -x ${ROOT}/usr/bin/qmerge-test ]]
-tend $? "qmerge-test: [R] installed expected files" || treedir "${ROOT}"
+tend $? "qmerge-test: [R] installed expected files" || die "$(treedir 
"${ROOT}")"
 
 order=$(echo "${out}" | awk '$1 == ">>>" && $2 ~ /^pkg_/ { printf "%s ", $NF 
}')
 [[ ${order} == "pkg_pretend pkg_setup pkg_preinst pkg_postinst " ]]
-tend $? "qmerge-test: [R] pkg_* order of execution" || printf '%s\n' 
"${order}" "${out}"
+tend $? "qmerge-test: [R] pkg_* order of execution" || die "$(printf '%s\n' 
"${order}" "${out}")"
 
 [[ -x ${ROOT}/usr/bin/qmerge-test && \
    -f ${ROOT}/etc/some.conf && \
    -f ${ROOT}/etc/another.conf && \
    -f ${ROOT}/etc/._cfg0000_some.conf ]]
-tend $? "qmerge-test: [R] re-installed expected files" || treedir "${ROOT}"
+tend $? "qmerge-test: [R] re-installed expected files" || die "$(treedir 
"${ROOT}")"
 
 # Finally do an unmerge.
 
@@ -64,17 +67,17 @@ echo alkdsjfalksdf > "${ROOT}/etc/some.conf"
 
 rm -f "${ROOT}/etc/._cfg0000_some.conf"
 out=$(yes | qmerge -FU qmerge-test)
-tend $? "qmerge-test: [C] uninstall" || echo "${out}"
+tend $? "qmerge-test: [C] uninstall" || die "${out}"
 
 order=$(echo "${out}" | awk '$1 == ">>>" { printf "%s ", $NF }')
 [[ ${order} == "pkg_prerm pkg_postrm " ]]
-tend $? "qmerge-test: [C] pkg_* order of execution" || printf '%s\n' 
"${order}" "${out}"
+tend $? "qmerge-test: [C] pkg_* order of execution" || die "$(printf '%s\n' 
"${order}" "${out}")"
 
 [[ ! -x ${ROOT}/usr/bin/qmerge-test && \
      -f ${ROOT}/etc/some.conf && \
    ! -f ${ROOT}/etc/another.conf && \
    ! -d ${ROOT}/var/db/pkg/sys-devel ]]
-tend $? "qmerge-test: [C] uninstalled expected files" || treedir "${ROOT}"
+tend $? "qmerge-test: [C] uninstalled expected files" || die "$(treedir 
"${ROOT}")"
 
 set -e
 

diff --git a/tests/quse/dotest b/tests/quse/dotest
index ada7bd9..93bef56 100755
--- a/tests/quse/dotest
+++ b/tests/quse/dotest
@@ -8,6 +8,10 @@ mktmpdir
 
 mkportdir "${as}/portdir"
 
+# check inference of PORTDIR with repos.conf
+q -evC PORTDIR
+q -ovC
+
 d=${PORTDIR}/profiles
 entries() {
        sed -e 's:#.*::' -e '/^$/d' "$1"

Reply via email to