diff --git a/bisect.c b/bisect.c index b63669cc9d..38b3891f3a 100644 --- a/bisect.c +++ b/bisect.c @@ -648,11 +648,14 @@ static struct commit_list *managed_skipped(struct commit_list *list, } static void bisect_rev_setup(struct repository *r, struct rev_info *revs, + struct strvec *rev_argv, const char *prefix, const char *bad_format, const char *good_format, int read_paths) { - struct strvec rev_argv = STRVEC_INIT; + struct setup_revision_opt opt = { + .free_removed_argv_elements = 1, + }; int i; repo_init_revisions(r, revs, prefix); @@ -660,17 +663,16 @@ static void bisect_rev_setup(struct repository *r, struct rev_info *revs, revs->commit_format = CMIT_FMT_UNSPECIFIED; /* rev_argv.argv[0] will be ignored by setup_revisions */ - strvec_push(&rev_argv, "bisect_rev_setup"); - strvec_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid)); + strvec_push(rev_argv, "bisect_rev_setup"); + strvec_pushf(rev_argv, bad_format, oid_to_hex(current_bad_oid)); for (i = 0; i < good_revs.nr; i++) - strvec_pushf(&rev_argv, good_format, + strvec_pushf(rev_argv, good_format, oid_to_hex(good_revs.oid + i)); - strvec_push(&rev_argv, "--"); + strvec_push(rev_argv, "--"); if (read_paths) - read_bisect_paths(&rev_argv); + read_bisect_paths(rev_argv); - setup_revisions(rev_argv.nr, rev_argv.v, revs, NULL); - /* XXX leak rev_argv, as "revs" may still be pointing to it */ + setup_revisions(rev_argv->nr, rev_argv->v, revs, &opt); } static void bisect_common(struct rev_info *revs) @@ -873,10 +875,11 @@ static enum bisect_error check_merge_bases(int rev_nr, struct commit **rev, int static int check_ancestors(struct repository *r, int rev_nr, struct commit **rev, const char *prefix) { + struct strvec rev_argv = STRVEC_INIT; struct rev_info revs; int res; - bisect_rev_setup(r, &revs, prefix, "^%s", "%s", 0); + bisect_rev_setup(r, &revs, &rev_argv, prefix, "^%s", "%s", 0); bisect_common(&revs); res = (revs.commits != NULL); @@ -885,6 +888,7 @@ static int check_ancestors(struct repository *r, int rev_nr, clear_commit_marks_many(rev_nr, rev, ALL_REV_FLAGS); release_revisions(&revs); + strvec_clear(&rev_argv); return res; } @@ -1010,6 +1014,7 @@ void read_bisect_terms(const char **read_bad, const char **read_good) */ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) { + struct strvec rev_argv = STRVEC_INIT; struct rev_info revs = REV_INFO_INIT; struct commit_list *tried; int reaches = 0, all = 0, nr, steps; @@ -1037,7 +1042,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) if (res) goto cleanup; - bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1); + bisect_rev_setup(r, &revs, &rev_argv, prefix, "%s", "^%s", 1); revs.first_parent_only = !!(bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY); revs.limited = 1; @@ -1054,7 +1059,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) */ res = error_if_skipped_commits(tried, NULL); if (res < 0) - return res; + goto cleanup; printf(_("%s was both %s and %s\n"), oid_to_hex(current_bad_oid), term_good, @@ -1112,6 +1117,7 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix) res = bisect_checkout(bisect_rev, no_checkout); cleanup: release_revisions(&revs); + strvec_clear(&rev_argv); return res; } diff --git a/builtin/log.c b/builtin/log.c index 88a5e98875..9b937d59b8 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -668,10 +668,10 @@ static void show_setup_revisions_tweak(struct rev_info *rev, int cmd_show(int argc, const char **argv, const char *prefix) { struct rev_info rev; - struct object_array_entry *objects; + unsigned int i; struct setup_revision_opt opt; struct pathspec match_all; - int i, count, ret = 0; + int ret = 0; init_log_defaults(); git_config(git_log_config, NULL); @@ -698,12 +698,10 @@ int cmd_show(int argc, const char **argv, const char *prefix) if (!rev.no_walk) return cmd_log_deinit(cmd_log_walk(&rev), &rev); - count = rev.pending.nr; - objects = rev.pending.objects; rev.diffopt.no_free = 1; - for (i = 0; i < count && !ret; i++) { - struct object *o = objects[i].item; - const char *name = objects[i].name; + for (i = 0; i < rev.pending.nr && !ret; i++) { + struct object *o = rev.pending.objects[i].item; + const char *name = rev.pending.objects[i].name; switch (o->type) { case OBJ_BLOB: ret = show_blob_object(&o->oid, &rev, name); @@ -726,7 +724,7 @@ int cmd_show(int argc, const char **argv, const char *prefix) if (!o) ret = error(_("could not read object %s"), oid_to_hex(oid)); - objects[i].item = o; + rev.pending.objects[i].item = o; i--; break; } @@ -743,11 +741,24 @@ int cmd_show(int argc, const char **argv, const char *prefix) rev.shown_one = 1; break; case OBJ_COMMIT: - rev.pending.nr = rev.pending.alloc = 0; - rev.pending.objects = NULL; + { + struct object_array old; + struct object_array blank = OBJECT_ARRAY_INIT; + + memcpy(&old, &rev.pending, sizeof(old)); + memcpy(&rev.pending, &blank, sizeof(rev.pending)); + add_object_array(o, name, &rev.pending); ret = cmd_log_walk_no_free(&rev); + + /* + * No need for + * object_array_clear(&pending). It was + * cleared already in prepare_revision_walk() + */ + memcpy(&rev.pending, &old, sizeof(rev.pending)); break; + } default: ret = error(_("unknown type: %d"), o->type); } diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c index fac52ade5e..b63f420ece 100644 --- a/builtin/submodule--helper.c +++ b/builtin/submodule--helper.c @@ -1104,6 +1104,9 @@ static int compute_summary_module_list(struct object_id *head_oid, { struct strvec diff_args = STRVEC_INIT; struct rev_info rev; + struct setup_revision_opt opt = { + .free_removed_argv_elements = 1, + }; struct module_cb_list list = MODULE_CB_LIST_INIT; int ret = 0; @@ -1121,7 +1124,7 @@ static int compute_summary_module_list(struct object_id *head_oid, init_revisions(&rev, info->prefix); rev.abbrev = 0; precompose_argv_prefix(diff_args.nr, diff_args.v, NULL); - setup_revisions(diff_args.nr, diff_args.v, &rev, NULL); + setup_revisions(diff_args.nr, diff_args.v, &rev, &opt); rev.diffopt.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK; rev.diffopt.format_callback = submodule_summary_callback; rev.diffopt.format_callback_data = &list; diff --git a/remote.c b/remote.c index e90dca1d56..618ad5a0f1 100644 --- a/remote.c +++ b/remote.c @@ -2147,6 +2147,9 @@ static int stat_branch_pair(const char *branch_name, const char *base, struct object_id oid; struct commit *ours, *theirs; struct rev_info revs; + struct setup_revision_opt opt = { + .free_removed_argv_elements = 1, + }; struct strvec argv = STRVEC_INIT; /* Cannot stat if what we used to build on no longer exists */ @@ -2181,7 +2184,7 @@ static int stat_branch_pair(const char *branch_name, const char *base, strvec_push(&argv, "--"); repo_init_revisions(the_repository, &revs, NULL); - setup_revisions(argv.nr, argv.v, &revs, NULL); + setup_revisions(argv.nr, argv.v, &revs, &opt); if (prepare_revision_walk(&revs)) die(_("revision walk setup failed")); diff --git a/revision.c b/revision.c index 87f1c117d1..f4eee11cc8 100644 --- a/revision.c +++ b/revision.c @@ -2784,6 +2784,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s const char *arg = argv[i]; if (strcmp(arg, "--")) continue; + if (opt && opt->free_removed_argv_elements) + free((char *)argv[i]); argv[i] = NULL; argc = i; if (argv[i + 1]) diff --git a/revision.h b/revision.h index e576845cdd..bb91e7ed91 100644 --- a/revision.h +++ b/revision.h @@ -375,7 +375,8 @@ struct setup_revision_opt { const char *def; void (*tweak)(struct rev_info *, struct setup_revision_opt *); unsigned int assume_dashdash:1, - allow_exclude_promisor_objects:1; + allow_exclude_promisor_objects:1, + free_removed_argv_elements:1; unsigned revarg_opt; }; int setup_revisions(int argc, const char **argv, struct rev_info *revs, diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c index 4e5553e202..45665ec19a 100644 --- a/t/helper/test-fast-rebase.c +++ b/t/helper/test-fast-rebase.c @@ -184,8 +184,6 @@ int cmd__fast_rebase(int argc, const char **argv) last_picked_commit = commit; last_commit = create_commit(result.tree, commit, last_commit); } - /* TODO: There should be some kind of rev_info_free(&revs) call... */ - memset(&revs, 0, sizeof(revs)); merge_switch_to_result(&merge_opt, head_tree, &result, 1, !result.clean); diff --git a/t/t0203-gettext-setlocale-sanity.sh b/t/t0203-gettext-setlocale-sanity.sh index 0ce1f22eff..86cff324ff 100755 --- a/t/t0203-gettext-setlocale-sanity.sh +++ b/t/t0203-gettext-setlocale-sanity.sh @@ -5,6 +5,7 @@ test_description="The Git C functions aren't broken by setlocale(3)" +TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh test_expect_success 'git show a ISO-8859-1 commit under C locale' ' diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh index 9fdbb2af80..45eef9457f 100755 --- a/t/t1020-subdirectory.sh +++ b/t/t1020-subdirectory.sh @@ -6,6 +6,7 @@ test_description='Try various core-level commands in subdirectory. ' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index bc46713a43..2eab6474f8 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -4,6 +4,7 @@ test_description='checkout into detached HEAD state' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_detached () { diff --git a/t/t3307-notes-man.sh b/t/t3307-notes-man.sh index 1aa366a410..ae316502c4 100755 --- a/t/t3307-notes-man.sh +++ b/t/t3307-notes-man.sh @@ -4,6 +4,7 @@ test_description='Examples from the git-notes man page Make sure the manual is not full of lies.' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t3920-crlf-messages.sh b/t/t3920-crlf-messages.sh index 0276edbe3d..4c661d4d54 100755 --- a/t/t3920-crlf-messages.sh +++ b/t/t3920-crlf-messages.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='Test ref-filter and pretty APIs for commit and tag messages using CRLF' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh LIB_CRLF_BRANCHES="" diff --git a/t/t4069-remerge-diff.sh b/t/t4069-remerge-diff.sh index 35f94957fc..9e7cac68b1 100755 --- a/t/t4069-remerge-diff.sh +++ b/t/t4069-remerge-diff.sh @@ -2,6 +2,7 @@ test_description='remerge-diff handling' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # This test is ort-specific diff --git a/t/t7007-show.sh b/t/t7007-show.sh index d6cc69e0f2..f908a4d1ab 100755 --- a/t/t7007-show.sh +++ b/t/t7007-show.sh @@ -2,6 +2,7 @@ test_description='git show' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh index ad1eb64ba0..aa004b70a8 100755 --- a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh +++ b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh @@ -5,6 +5,7 @@ test_description='pre-commit and pre-merge-commit hooks' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'root commit' ' diff --git a/t/t9122-git-svn-author.sh b/t/t9122-git-svn-author.sh index 527ba3d293..0fc289ae0f 100755 --- a/t/t9122-git-svn-author.sh +++ b/t/t9122-git-svn-author.sh @@ -2,7 +2,6 @@ test_description='git svn authorship' -TEST_FAILS_SANITIZE_LEAK=true . ./lib-git-svn.sh test_expect_success 'setup svn repository' ' diff --git a/t/t9162-git-svn-dcommit-interactive.sh b/t/t9162-git-svn-dcommit-interactive.sh index e2aa8ed88a..b3ce033a0d 100755 --- a/t/t9162-git-svn-dcommit-interactive.sh +++ b/t/t9162-git-svn-dcommit-interactive.sh @@ -4,7 +4,6 @@ test_description='git svn dcommit --interactive series' -TEST_FAILS_SANITIZE_LEAK=true . ./lib-git-svn.sh test_expect_success 'initialize repo' '