Skip to content

Commit 81afc79

Browse files
newrengitster
authored andcommitted
merge-ort: fix small memory leak in unique_path()
The struct strmap paths member of merge_options_internal is perhaps the most central data structure to all of merge-ort. Because all the paths involved in the merge need to be kept until the merge is complete, this "paths" data structure traditionally took responsibility for owning all the allocated paths. When the merge is over, those paths were free()d as part of free()ing this strmap. In commit 6697ee0 (merge-ort: switch our strmaps over to using memory pools, 2021-07-30), we changed the allocations for pathnames to come from a memory pool. That meant the ownership changed slightly; there were no individual free() calls to make, instead the memory pool owned all those paths and they were free()d all at once. Unfortunately unique_path() was written presuming the pre-memory-pool model, and allocated a path on the heap and left it in the strmap for later free()ing. Modify it to return a path allocated from the memory pool instead. Note that there's one instance -- in record_conflicted_index_entries() -- where the returned string from unique_path() was only used very temporarily and thus had been immediately free()'d. This codepath was associated with an ugly skip-worktree workaround that has since been better fixed by the in-flight en/present-despite-skipped topic. This workaround probably makes sense to excise once that topic merges down, but for now, just remove the immediate free() and allow the returned string to be free()d when the memory pool is released. This fixes the following memory leak as reported by valgrind: ==PID== 65 bytes in 1 blocks are definitely lost in loss record 79 of 134 ==PID== at 0xADDRESS: malloc ==PID== by 0xADDRESS: realloc ==PID== by 0xADDRESS: xrealloc (wrapper.c:126) ==PID== by 0xADDRESS: strbuf_grow (strbuf.c:98) ==PID== by 0xADDRESS: strbuf_vaddf (strbuf.c:394) ==PID== by 0xADDRESS: strbuf_addf (strbuf.c:335) ==PID== by 0xADDRESS: unique_path (merge-ort.c:733) ==PID== by 0xADDRESS: process_entry (merge-ort.c:3678) ==PID== by 0xADDRESS: process_entries (merge-ort.c:4037) ==PID== by 0xADDRESS: merge_ort_nonrecursive_internal (merge-ort.c:4621) ==PID== by 0xADDRESS: merge_ort_internal (merge-ort.c:4709) ==PID== by 0xADDRESS: merge_incore_recursive (merge-ort.c:4760) ==PID== by 0xADDRESS: merge_ort_recursive (merge-ort-wrappers.c:57) ==PID== by 0xADDRESS: try_merge_strategy (merge.c:753) Reported-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8d60e9d commit 81afc79

File tree

1 file changed

+12
-9
lines changed

1 file changed

+12
-9
lines changed

merge-ort.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -722,13 +722,15 @@ static void add_flattened_path(struct strbuf *out, const char *s)
722722
out->buf[i] = '_';
723723
}
724724

725-
static char *unique_path(struct strmap *existing_paths,
725+
static char *unique_path(struct merge_options *opt,
726726
const char *path,
727727
const char *branch)
728728
{
729+
char *ret = NULL;
729730
struct strbuf newpath = STRBUF_INIT;
730731
int suffix = 0;
731732
size_t base_len;
733+
struct strmap *existing_paths = &opt->priv->paths;
732734

733735
strbuf_addf(&newpath, "%s~", path);
734736
add_flattened_path(&newpath, branch);
@@ -739,7 +741,11 @@ static char *unique_path(struct strmap *existing_paths,
739741
strbuf_addf(&newpath, "_%d", suffix++);
740742
}
741743

742-
return strbuf_detach(&newpath, NULL);
744+
/* Track the new path in our memory pool */
745+
ret = mem_pool_alloc(&opt->priv->pool, newpath.len + 1);
746+
memcpy(ret, newpath.buf, newpath.len + 1);
747+
strbuf_release(&newpath);
748+
return ret;
743749
}
744750

745751
/*** Function Grouping: functions related to collect_merge_info() ***/
@@ -3674,7 +3680,7 @@ static void process_entry(struct merge_options *opt,
36743680
*/
36753681
df_file_index = (ci->dirmask & (1 << 1)) ? 2 : 1;
36763682
branch = (df_file_index == 1) ? opt->branch1 : opt->branch2;
3677-
path = unique_path(&opt->priv->paths, path, branch);
3683+
path = unique_path(opt, path, branch);
36783684
strmap_put(&opt->priv->paths, path, new_ci);
36793685

36803686
path_msg(opt, path, 0,
@@ -3799,14 +3805,12 @@ static void process_entry(struct merge_options *opt,
37993805
/* Insert entries into opt->priv_paths */
38003806
assert(rename_a || rename_b);
38013807
if (rename_a) {
3802-
a_path = unique_path(&opt->priv->paths,
3803-
path, opt->branch1);
3808+
a_path = unique_path(opt, path, opt->branch1);
38043809
strmap_put(&opt->priv->paths, a_path, ci);
38053810
}
38063811

38073812
if (rename_b)
3808-
b_path = unique_path(&opt->priv->paths,
3809-
path, opt->branch2);
3813+
b_path = unique_path(opt, path, opt->branch2);
38103814
else
38113815
b_path = path;
38123816
strmap_put(&opt->priv->paths, b_path, new_ci);
@@ -4194,15 +4198,14 @@ static int record_conflicted_index_entries(struct merge_options *opt)
41944198
struct stat st;
41954199

41964200
if (!lstat(path, &st)) {
4197-
char *new_name = unique_path(&opt->priv->paths,
4201+
char *new_name = unique_path(opt,
41984202
path,
41994203
"cruft");
42004204

42014205
path_msg(opt, path, 1,
42024206
_("Note: %s not up to date and in way of checking out conflicted version; old copy renamed to %s"),
42034207
path, new_name);
42044208
errs |= rename(path, new_name);
4205-
free(new_name);
42064209
}
42074210
errs |= checkout_entry(ce, &state, NULL, NULL);
42084211
}

0 commit comments

Comments
 (0)