From: Junio C Hamano Date: Wed, 15 Nov 2017 03:14:28 +0000 (+0900) Subject: Merge branch 'ma/bisect-leakfix' X-Git-Tag: v2.16.0-rc0~134 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/f116163171b875f9b58c6f6755bec85460e9b8b8?ds=inline;hp=-c Merge branch 'ma/bisect-leakfix' Leak fixes. * ma/bisect-leakfix: bisect: fix memory leak when returning best element bisect: fix off-by-one error in `best_bisection_sorted()` bisect: fix memory leak in `find_bisection()` bisect: change calling-convention of `find_bisection()` --- f116163171b875f9b58c6f6755bec85460e9b8b8 diff --combined bisect.c index fda2c4a186,3756f127b0..de551c6d5e --- a/bisect.c +++ b/bisect.c @@@ -226,10 -226,11 +226,11 @@@ static struct commit_list *best_bisecti add_name_decoration(DECORATION_NONE, buf.buf, obj); p->item = array[i].commit; - p = p->next; + if (i < cnt - 1) + p = p->next; } - if (p) - p->next = NULL; + free_commit_list(p->next); + p->next = NULL; strbuf_release(&buf); free(array); return list; @@@ -360,28 -361,29 +361,29 @@@ static struct commit_list *do_find_bise return best_bisection_sorted(list, nr); } - struct commit_list *find_bisection(struct commit_list *list, - int *reaches, int *all, - int find_all) + void find_bisection(struct commit_list **commit_list, int *reaches, + int *all, int find_all) { int nr, on_list; - struct commit_list *p, *best, *next, *last; + struct commit_list *list, *p, *best, *next, *last; int *weights; - show_list("bisection 2 entry", 0, 0, list); + show_list("bisection 2 entry", 0, 0, *commit_list); /* * Count the number of total and tree-changing items on the * list, while reversing the list. */ - for (nr = on_list = 0, last = NULL, p = list; + for (nr = on_list = 0, last = NULL, p = *commit_list; p; p = next) { unsigned flags = p->item->object.flags; next = p->next; - if (flags & UNINTERESTING) + if (flags & UNINTERESTING) { + free(p); continue; + } p->next = last; last = p; if (!(flags & TREESAME)) @@@ -397,12 -399,16 +399,16 @@@ /* Do the real work of finding bisection commit. */ best = do_find_bisection(list, nr, weights, find_all); if (best) { - if (!find_all) + if (!find_all) { + list->item = best->item; + free_commit_list(list->next); + best = list; best->next = NULL; + } *reaches = weight(best); } free(weights); - return best; + *commit_list = best; } static int register_ref(const char *refname, const struct object_id *oid, @@@ -433,12 -439,7 +439,12 @@@ static int read_bisect_refs(void static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static GIT_PATH_FUNC(git_path_bisect_expected_rev, "BISECT_EXPECTED_REV") +static GIT_PATH_FUNC(git_path_bisect_ancestors_ok, "BISECT_ANCESTORS_OK") +static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN") +static GIT_PATH_FUNC(git_path_bisect_start, "BISECT_START") +static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG") static GIT_PATH_FUNC(git_path_bisect_terms, "BISECT_TERMS") +static GIT_PATH_FUNC(git_path_head_name, "head-name") static void read_bisect_paths(struct argv_array *array) { @@@ -690,12 -691,11 +696,12 @@@ static int bisect_checkout(const struc char bisect_rev_hex[GIT_MAX_HEXSZ + 1]; memcpy(bisect_rev_hex, oid_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1); - update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev->hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); + update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR); argv_checkout[2] = bisect_rev_hex; if (no_checkout) { - update_ref(NULL, "BISECT_HEAD", bisect_rev->hash, NULL, 0, UPDATE_REFS_DIE_ON_ERR); + update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0, + UPDATE_REFS_DIE_ON_ERR); } else { int res; res = run_command_v_opt(argv_checkout, RUN_GIT_CMD); @@@ -960,8 -960,7 +966,7 @@@ int bisect_next_all(const char *prefix bisect_common(&revs); - revs.commits = find_bisection(revs.commits, &reaches, &all, - !!skipped_revs.nr); + find_bisection(&revs.commits, &reaches, &all, !!skipped_revs.nr); revs.commits = managed_skipped(revs.commits, &tried); if (!revs.commits) { @@@ -1050,40 -1049,3 +1055,40 @@@ int estimate_bisect_steps(int all return (e < 3 * x) ? n : n - 1; } + +static int mark_for_removal(const char *refname, const struct object_id *oid, + int flag, void *cb_data) +{ + struct string_list *refs = cb_data; + char *ref = xstrfmt("refs/bisect%s", refname); + string_list_append(refs, ref); + return 0; +} + +int bisect_clean_state(void) +{ + int result = 0; + + /* There may be some refs packed during bisection */ + struct string_list refs_for_removal = STRING_LIST_INIT_NODUP; + for_each_ref_in("refs/bisect", mark_for_removal, (void *) &refs_for_removal); + string_list_append(&refs_for_removal, xstrdup("BISECT_HEAD")); + result = delete_refs("bisect: remove", &refs_for_removal, REF_NODEREF); + refs_for_removal.strdup_strings = 1; + string_list_clear(&refs_for_removal, 0); + unlink_or_warn(git_path_bisect_expected_rev()); + unlink_or_warn(git_path_bisect_ancestors_ok()); + unlink_or_warn(git_path_bisect_log()); + unlink_or_warn(git_path_bisect_names()); + unlink_or_warn(git_path_bisect_run()); + unlink_or_warn(git_path_bisect_terms()); + /* Cleanup head-name if it got left by an old version of git-bisect */ + unlink_or_warn(git_path_head_name()); + /* + * Cleanup BISECT_START last to support the --no-checkout option + * introduced in the commit 4796e823a. + */ + unlink_or_warn(git_path_bisect_start()); + + return result; +} diff --combined bisect.h index 0ae63d4616,c535e6d12e..a5d9248a47 --- a/bisect.h +++ b/bisect.h @@@ -1,9 -1,15 +1,15 @@@ #ifndef BISECT_H #define BISECT_H - extern struct commit_list *find_bisection(struct commit_list *list, - int *reaches, int *all, - int find_all); + /* + * Find bisection. If something is found, `reaches` will be the number of + * commits that the best commit reaches. `all` will be the count of + * non-SAMETREE commits. If nothing is found, `list` will be NULL. + * Otherwise, it will be either all non-SAMETREE commits or the single + * best commit, as chosen by `find_all`. + */ + extern void find_bisection(struct commit_list **list, int *reaches, int *all, + int find_all); extern struct commit_list *filter_skipped(struct commit_list *list, struct commit_list **tried, @@@ -28,6 -34,4 +34,6 @@@ extern int estimate_bisect_steps(int al extern void read_bisect_terms(const char **bad, const char **good); +extern int bisect_clean_state(void); + #endif diff --combined builtin/rev-list.c index 8034d2eff2,fb1c36af6a..4032eb3811 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@@ -258,14 -258,14 +258,14 @@@ static int show_bisect_vars(struct rev_ } static int show_object_fast( - const unsigned char *sha1, + const struct object_id *oid, enum object_type type, int exclude, uint32_t name_hash, struct packed_git *found_pack, off_t found_offset) { - fprintf(stdout, "%s\n", sha1_to_hex(sha1)); + fprintf(stdout, "%s\n", oid_to_hex(oid)); return 1; } @@@ -294,7 -294,7 +294,7 @@@ int cmd_rev_list(int argc, const char * if (revs.bisect) bisect_list = 1; - if (DIFF_OPT_TST(&revs.diffopt, QUICK)) + if (revs.diffopt.flags.quick) info.flags |= REV_LIST_QUIET; for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; @@@ -397,8 -397,7 +397,7 @@@ if (bisect_list) { int reaches = reaches, all = all; - revs.commits = find_bisection(revs.commits, &reaches, &all, - bisect_find_all); + find_bisection(&revs.commits, &reaches, &all, bisect_find_all); if (bisect_show_vars) return show_bisect_vars(&info, reaches, all);