mirror of
https://github.com/git/git
synced 2024-10-03 23:29:36 +00:00
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()
This commit is contained in:
commit
83489a5b20
28
bisect.c
28
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,
|
static void bisect_rev_setup(struct repository *r, struct rev_info *revs,
|
||||||
|
struct strvec *rev_argv,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
const char *bad_format, const char *good_format,
|
const char *bad_format, const char *good_format,
|
||||||
int read_paths)
|
int read_paths)
|
||||||
{
|
{
|
||||||
struct strvec rev_argv = STRVEC_INIT;
|
struct setup_revision_opt opt = {
|
||||||
|
.free_removed_argv_elements = 1,
|
||||||
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
repo_init_revisions(r, revs, prefix);
|
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;
|
revs->commit_format = CMIT_FMT_UNSPECIFIED;
|
||||||
|
|
||||||
/* rev_argv.argv[0] will be ignored by setup_revisions */
|
/* rev_argv.argv[0] will be ignored by setup_revisions */
|
||||||
strvec_push(&rev_argv, "bisect_rev_setup");
|
strvec_push(rev_argv, "bisect_rev_setup");
|
||||||
strvec_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid));
|
strvec_pushf(rev_argv, bad_format, oid_to_hex(current_bad_oid));
|
||||||
for (i = 0; i < good_revs.nr; i++)
|
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));
|
oid_to_hex(good_revs.oid + i));
|
||||||
strvec_push(&rev_argv, "--");
|
strvec_push(rev_argv, "--");
|
||||||
if (read_paths)
|
if (read_paths)
|
||||||
read_bisect_paths(&rev_argv);
|
read_bisect_paths(rev_argv);
|
||||||
|
|
||||||
setup_revisions(rev_argv.nr, rev_argv.v, revs, NULL);
|
setup_revisions(rev_argv->nr, rev_argv->v, revs, &opt);
|
||||||
/* XXX leak rev_argv, as "revs" may still be pointing to it */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bisect_common(struct rev_info *revs)
|
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,
|
static int check_ancestors(struct repository *r, int rev_nr,
|
||||||
struct commit **rev, const char *prefix)
|
struct commit **rev, const char *prefix)
|
||||||
{
|
{
|
||||||
|
struct strvec rev_argv = STRVEC_INIT;
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
int res;
|
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);
|
bisect_common(&revs);
|
||||||
res = (revs.commits != NULL);
|
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);
|
clear_commit_marks_many(rev_nr, rev, ALL_REV_FLAGS);
|
||||||
|
|
||||||
release_revisions(&revs);
|
release_revisions(&revs);
|
||||||
|
strvec_clear(&rev_argv);
|
||||||
return res;
|
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)
|
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 rev_info revs = REV_INFO_INIT;
|
||||||
struct commit_list *tried;
|
struct commit_list *tried;
|
||||||
int reaches = 0, all = 0, nr, steps;
|
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)
|
if (res)
|
||||||
goto cleanup;
|
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.first_parent_only = !!(bisect_flags & FIND_BISECTION_FIRST_PARENT_ONLY);
|
||||||
revs.limited = 1;
|
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);
|
res = error_if_skipped_commits(tried, NULL);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return res;
|
goto cleanup;
|
||||||
printf(_("%s was both %s and %s\n"),
|
printf(_("%s was both %s and %s\n"),
|
||||||
oid_to_hex(current_bad_oid),
|
oid_to_hex(current_bad_oid),
|
||||||
term_good,
|
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);
|
res = bisect_checkout(bisect_rev, no_checkout);
|
||||||
cleanup:
|
cleanup:
|
||||||
release_revisions(&revs);
|
release_revisions(&revs);
|
||||||
|
strvec_clear(&rev_argv);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
int cmd_show(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
struct rev_info rev;
|
struct rev_info rev;
|
||||||
struct object_array_entry *objects;
|
unsigned int i;
|
||||||
struct setup_revision_opt opt;
|
struct setup_revision_opt opt;
|
||||||
struct pathspec match_all;
|
struct pathspec match_all;
|
||||||
int i, count, ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
init_log_defaults();
|
init_log_defaults();
|
||||||
git_config(git_log_config, NULL);
|
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)
|
if (!rev.no_walk)
|
||||||
return cmd_log_deinit(cmd_log_walk(&rev), &rev);
|
return cmd_log_deinit(cmd_log_walk(&rev), &rev);
|
||||||
|
|
||||||
count = rev.pending.nr;
|
|
||||||
objects = rev.pending.objects;
|
|
||||||
rev.diffopt.no_free = 1;
|
rev.diffopt.no_free = 1;
|
||||||
for (i = 0; i < count && !ret; i++) {
|
for (i = 0; i < rev.pending.nr && !ret; i++) {
|
||||||
struct object *o = objects[i].item;
|
struct object *o = rev.pending.objects[i].item;
|
||||||
const char *name = objects[i].name;
|
const char *name = rev.pending.objects[i].name;
|
||||||
switch (o->type) {
|
switch (o->type) {
|
||||||
case OBJ_BLOB:
|
case OBJ_BLOB:
|
||||||
ret = show_blob_object(&o->oid, &rev, name);
|
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)
|
if (!o)
|
||||||
ret = error(_("could not read object %s"),
|
ret = error(_("could not read object %s"),
|
||||||
oid_to_hex(oid));
|
oid_to_hex(oid));
|
||||||
objects[i].item = o;
|
rev.pending.objects[i].item = o;
|
||||||
i--;
|
i--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -743,11 +741,24 @@ int cmd_show(int argc, const char **argv, const char *prefix)
|
||||||
rev.shown_one = 1;
|
rev.shown_one = 1;
|
||||||
break;
|
break;
|
||||||
case OBJ_COMMIT:
|
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);
|
add_object_array(o, name, &rev.pending);
|
||||||
ret = cmd_log_walk_no_free(&rev);
|
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;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ret = error(_("unknown type: %d"), o->type);
|
ret = error(_("unknown type: %d"), o->type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1104,6 +1104,9 @@ static int compute_summary_module_list(struct object_id *head_oid,
|
||||||
{
|
{
|
||||||
struct strvec diff_args = STRVEC_INIT;
|
struct strvec diff_args = STRVEC_INIT;
|
||||||
struct rev_info rev;
|
struct rev_info rev;
|
||||||
|
struct setup_revision_opt opt = {
|
||||||
|
.free_removed_argv_elements = 1,
|
||||||
|
};
|
||||||
struct module_cb_list list = MODULE_CB_LIST_INIT;
|
struct module_cb_list list = MODULE_CB_LIST_INIT;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -1121,7 +1124,7 @@ static int compute_summary_module_list(struct object_id *head_oid,
|
||||||
init_revisions(&rev, info->prefix);
|
init_revisions(&rev, info->prefix);
|
||||||
rev.abbrev = 0;
|
rev.abbrev = 0;
|
||||||
precompose_argv_prefix(diff_args.nr, diff_args.v, NULL);
|
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.output_format = DIFF_FORMAT_NO_OUTPUT | DIFF_FORMAT_CALLBACK;
|
||||||
rev.diffopt.format_callback = submodule_summary_callback;
|
rev.diffopt.format_callback = submodule_summary_callback;
|
||||||
rev.diffopt.format_callback_data = &list;
|
rev.diffopt.format_callback_data = &list;
|
||||||
|
|
5
remote.c
5
remote.c
|
@ -2147,6 +2147,9 @@ static int stat_branch_pair(const char *branch_name, const char *base,
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
struct commit *ours, *theirs;
|
struct commit *ours, *theirs;
|
||||||
struct rev_info revs;
|
struct rev_info revs;
|
||||||
|
struct setup_revision_opt opt = {
|
||||||
|
.free_removed_argv_elements = 1,
|
||||||
|
};
|
||||||
struct strvec argv = STRVEC_INIT;
|
struct strvec argv = STRVEC_INIT;
|
||||||
|
|
||||||
/* Cannot stat if what we used to build on no longer exists */
|
/* 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, "--");
|
strvec_push(&argv, "--");
|
||||||
|
|
||||||
repo_init_revisions(the_repository, &revs, NULL);
|
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))
|
if (prepare_revision_walk(&revs))
|
||||||
die(_("revision walk setup failed"));
|
die(_("revision walk setup failed"));
|
||||||
|
|
||||||
|
|
|
@ -2784,6 +2784,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
if (strcmp(arg, "--"))
|
if (strcmp(arg, "--"))
|
||||||
continue;
|
continue;
|
||||||
|
if (opt && opt->free_removed_argv_elements)
|
||||||
|
free((char *)argv[i]);
|
||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
argc = i;
|
argc = i;
|
||||||
if (argv[i + 1])
|
if (argv[i + 1])
|
||||||
|
|
|
@ -375,7 +375,8 @@ struct setup_revision_opt {
|
||||||
const char *def;
|
const char *def;
|
||||||
void (*tweak)(struct rev_info *, struct setup_revision_opt *);
|
void (*tweak)(struct rev_info *, struct setup_revision_opt *);
|
||||||
unsigned int assume_dashdash:1,
|
unsigned int assume_dashdash:1,
|
||||||
allow_exclude_promisor_objects:1;
|
allow_exclude_promisor_objects:1,
|
||||||
|
free_removed_argv_elements:1;
|
||||||
unsigned revarg_opt;
|
unsigned revarg_opt;
|
||||||
};
|
};
|
||||||
int setup_revisions(int argc, const char **argv, struct rev_info *revs,
|
int setup_revisions(int argc, const char **argv, struct rev_info *revs,
|
||||||
|
|
|
@ -184,8 +184,6 @@ int cmd__fast_rebase(int argc, const char **argv)
|
||||||
last_picked_commit = commit;
|
last_picked_commit = commit;
|
||||||
last_commit = create_commit(result.tree, commit, last_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);
|
merge_switch_to_result(&merge_opt, head_tree, &result, 1, !result.clean);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
test_description="The Git C functions aren't broken by setlocale(3)"
|
test_description="The Git C functions aren't broken by setlocale(3)"
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./lib-gettext.sh
|
. ./lib-gettext.sh
|
||||||
|
|
||||||
test_expect_success 'git show a ISO-8859-1 commit under C locale' '
|
test_expect_success 'git show a ISO-8859-1 commit under C locale' '
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
test_description='Try various core-level commands in subdirectory.
|
test_description='Try various core-level commands in subdirectory.
|
||||||
'
|
'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
. "$TEST_DIRECTORY"/lib-read-tree.sh
|
. "$TEST_DIRECTORY"/lib-read-tree.sh
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ test_description='checkout into detached HEAD state'
|
||||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
check_detached () {
|
check_detached () {
|
||||||
|
|
|
@ -4,6 +4,7 @@ test_description='Examples from the git-notes man page
|
||||||
|
|
||||||
Make sure the manual is not full of lies.'
|
Make sure the manual is not full of lies.'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'setup' '
|
test_expect_success 'setup' '
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
test_description='Test ref-filter and pretty APIs for commit and tag messages using CRLF'
|
test_description='Test ref-filter and pretty APIs for commit and tag messages using CRLF'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
LIB_CRLF_BRANCHES=""
|
LIB_CRLF_BRANCHES=""
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
test_description='remerge-diff handling'
|
test_description='remerge-diff handling'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
# This test is ort-specific
|
# This test is ort-specific
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
test_description='git show'
|
test_description='git show'
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success setup '
|
test_expect_success setup '
|
||||||
|
|
|
@ -5,6 +5,7 @@ test_description='pre-commit and pre-merge-commit hooks'
|
||||||
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
|
TEST_PASSES_SANITIZE_LEAK=true
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'root commit' '
|
test_expect_success 'root commit' '
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
test_description='git svn authorship'
|
test_description='git svn authorship'
|
||||||
|
|
||||||
TEST_FAILS_SANITIZE_LEAK=true
|
|
||||||
. ./lib-git-svn.sh
|
. ./lib-git-svn.sh
|
||||||
|
|
||||||
test_expect_success 'setup svn repository' '
|
test_expect_success 'setup svn repository' '
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
test_description='git svn dcommit --interactive series'
|
test_description='git svn dcommit --interactive series'
|
||||||
|
|
||||||
TEST_FAILS_SANITIZE_LEAK=true
|
|
||||||
. ./lib-git-svn.sh
|
. ./lib-git-svn.sh
|
||||||
|
|
||||||
test_expect_success 'initialize repo' '
|
test_expect_success 'initialize repo' '
|
||||||
|
|
Loading…
Reference in a new issue