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"