Browse Source

Merge branch 'ab/plug-revisions-leak'

Plug a bit more leaks in the revisions API.

* ab/plug-revisions-leak:
  revisions API: don't leak memory on argv elements that need free()-ing
  bisect.c: partially fix bisect_rev_setup() memory leak
  log: refactor "rev.pending" code in cmd_show()
  log: fix a memory leak in "git show <revision>..."
  test-fast-rebase helper: use release_revisions() (again)
  bisect.c: add missing "goto" for release_revisions()
maint
Junio C Hamano 3 years ago
parent
commit
83489a5b20
  1. 28
      bisect.c
  2. 31
      builtin/log.c
  3. 5
      builtin/submodule--helper.c
  4. 5
      remote.c
  5. 2
      revision.c
  6. 3
      revision.h
  7. 2
      t/helper/test-fast-rebase.c
  8. 1
      t/t0203-gettext-setlocale-sanity.sh
  9. 1
      t/t1020-subdirectory.sh
  10. 1
      t/t2020-checkout-detach.sh
  11. 1
      t/t3307-notes-man.sh
  12. 2
      t/t3920-crlf-messages.sh
  13. 1
      t/t4069-remerge-diff.sh
  14. 1
      t/t7007-show.sh
  15. 1
      t/t7503-pre-commit-and-pre-merge-commit-hooks.sh
  16. 1
      t/t9122-git-svn-author.sh
  17. 1
      t/t9162-git-svn-dcommit-interactive.sh

28
bisect.c

@ -648,11 +648,14 @@ static struct commit_list *managed_skipped(struct commit_list *list, @@ -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, @@ -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 @@ -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, @@ -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) @@ -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) @@ -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) @@ -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) @@ -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;
}


31
builtin/log.c

@ -668,10 +668,10 @@ static void show_setup_revisions_tweak(struct rev_info *rev, @@ -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) @@ -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) @@ -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) @@ -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);
}

5
builtin/submodule--helper.c

@ -1104,6 +1104,9 @@ static int compute_summary_module_list(struct object_id *head_oid, @@ -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, @@ -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;

5
remote.c

@ -2147,6 +2147,9 @@ static int stat_branch_pair(const char *branch_name, const char *base, @@ -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, @@ -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"));


2
revision.c

@ -2784,6 +2784,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s @@ -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])

3
revision.h

@ -375,7 +375,8 @@ struct setup_revision_opt { @@ -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,

2
t/helper/test-fast-rebase.c

@ -184,8 +184,6 @@ int cmd__fast_rebase(int argc, const char **argv) @@ -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);


1
t/t0203-gettext-setlocale-sanity.sh

@ -5,6 +5,7 @@ @@ -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' '

1
t/t1020-subdirectory.sh

@ -6,6 +6,7 @@ @@ -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


1
t/t2020-checkout-detach.sh

@ -4,6 +4,7 @@ test_description='checkout into detached HEAD state' @@ -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 () {

1
t/t3307-notes-man.sh

@ -4,6 +4,7 @@ test_description='Examples from the git-notes man page @@ -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' '

2
t/t3920-crlf-messages.sh

@ -1,6 +1,8 @@ @@ -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=""

1
t/t4069-remerge-diff.sh

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@

test_description='remerge-diff handling'

TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh

# This test is ort-specific

1
t/t7007-show.sh

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@

test_description='git show'

TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh

test_expect_success setup '

1
t/t7503-pre-commit-and-pre-merge-commit-hooks.sh

@ -5,6 +5,7 @@ test_description='pre-commit and pre-merge-commit hooks' @@ -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' '

1
t/t9122-git-svn-author.sh

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@

test_description='git svn authorship'

TEST_FAILS_SANITIZE_LEAK=true
. ./lib-git-svn.sh

test_expect_success 'setup svn repository' '

1
t/t9162-git-svn-dcommit-interactive.sh

@ -4,7 +4,6 @@ @@ -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' '

Loading…
Cancel
Save