Skip to content

Commit 33d0dda

Browse files
avargitster
authored andcommitted
checkout: avoid "struct unpack_trees_options" leak
In 1c41d28 (unpack_trees_options: free messages when done, 2018-05-21) we started calling clear_unpack_trees_porcelain() on this codepath, but missed this error path. We could call clear_unpack_trees_porcelain() just before we error() and return when unmerged_cache() fails, but the more correct fix is to not have the unmerged_cache() check happen in the middle of our "topts" setup. Before 23cbf11 (merge-recursive: porcelain messages for checkout, 2010-08-11) we would not malloc() to setup our "topts", which is when this started to leak on the error path. Before that this code wasn't conflating the setup of "topts" and the unmerged_cache() call in any meaningful way. The initial version in 782c2d6 (Build in checkout, 2008-02-07) just does a "memset" of it, and initializes a single struct member. Then in 8ccba00 (unpack-trees: allow Porcelain to give different error messages, 2008-05-17) we added the initialization of the error message, which as noted above finally started leaking in 23cbf11. Let's fix the memory leak, and avoid future issues by initializing the "topts" with a helper function. There are no functional changes here. Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent e72e12c commit 33d0dda

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

builtin/checkout.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,26 @@ static void setup_branch_path(struct branch_info *branch)
710710
branch->path = strbuf_detach(&buf, NULL);
711711
}
712712

713+
static void init_topts(struct unpack_trees_options *topts, int merge,
714+
int show_progress, int overwrite_ignore,
715+
struct commit *old_commit)
716+
{
717+
memset(topts, 0, sizeof(*topts));
718+
topts->head_idx = -1;
719+
topts->src_index = &the_index;
720+
topts->dst_index = &the_index;
721+
722+
setup_unpack_trees_porcelain(topts, "checkout");
723+
724+
topts->initial_checkout = is_cache_unborn();
725+
topts->update = 1;
726+
topts->merge = 1;
727+
topts->quiet = merge && old_commit;
728+
topts->verbose_update = show_progress;
729+
topts->fn = twoway_merge;
730+
topts->preserve_ignored = !overwrite_ignore;
731+
}
732+
713733
static int merge_working_tree(const struct checkout_opts *opts,
714734
struct branch_info *old_branch_info,
715735
struct branch_info *new_branch_info,
@@ -740,13 +760,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
740760
struct unpack_trees_options topts;
741761
const struct object_id *old_commit_oid;
742762

743-
memset(&topts, 0, sizeof(topts));
744-
topts.head_idx = -1;
745-
topts.src_index = &the_index;
746-
topts.dst_index = &the_index;
747-
748-
setup_unpack_trees_porcelain(&topts, "checkout");
749-
750763
refresh_cache(REFRESH_QUIET);
751764

752765
if (unmerged_cache()) {
@@ -755,17 +768,12 @@ static int merge_working_tree(const struct checkout_opts *opts,
755768
}
756769

757770
/* 2-way merge to the new branch */
758-
topts.initial_checkout = is_cache_unborn();
759-
topts.update = 1;
760-
topts.merge = 1;
761-
topts.quiet = opts->merge && old_branch_info->commit;
762-
topts.verbose_update = opts->show_progress;
763-
topts.fn = twoway_merge;
771+
init_topts(&topts, opts->merge, opts->show_progress,
772+
opts->overwrite_ignore, old_branch_info->commit);
764773
init_checkout_metadata(&topts.meta, new_branch_info->refname,
765774
new_branch_info->commit ?
766775
&new_branch_info->commit->object.oid :
767776
&new_branch_info->oid, NULL);
768-
topts.preserve_ignored = !opts->overwrite_ignore;
769777

770778
old_commit_oid = old_branch_info->commit ?
771779
&old_branch_info->commit->object.oid :

0 commit comments

Comments
 (0)