Skip to content

Commit 5ce08ed

Browse files
pks-tgitster
authored andcommitted
line-log: fix several memory leaks
As described in "line-log.c" itself, the code is "leaking like a sieve". These leaks are all of rather trivial nature, so this commit plugs them without going too much into details for each of those leaks. The leaks are hit by t4211, but plugging them alone does not make the full test suite pass. The remaining leaks are unrelated to the line-log subsystem. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a5aecb2 commit 5ce08ed

File tree

1 file changed

+35
-19
lines changed

1 file changed

+35
-19
lines changed

line-log.c

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,10 @@ static void line_log_data_init(struct line_log_data *r)
248248
static void line_log_data_clear(struct line_log_data *r)
249249
{
250250
range_set_release(&r->ranges);
251+
free(r->path);
251252
if (r->pair)
252253
diff_free_filepair(r->pair);
254+
diff_ranges_release(&r->diff);
253255
}
254256

255257
static void free_line_log_data(struct line_log_data *r)
@@ -571,7 +573,8 @@ parse_lines(struct repository *r, struct commit *commit,
571573
struct line_log_data *p;
572574

573575
for_each_string_list_item(item, args) {
574-
const char *name_part, *range_part;
576+
const char *name_part;
577+
char *range_part;
575578
char *full_name;
576579
struct diff_filespec *spec;
577580
long begin = 0, end = 0;
@@ -615,6 +618,7 @@ parse_lines(struct repository *r, struct commit *commit,
615618

616619
free_filespec(spec);
617620
FREE_AND_NULL(ends);
621+
free(range_part);
618622
}
619623

620624
for (p = ranges; p; p = p->next)
@@ -760,15 +764,13 @@ static void parse_pathspec_from_ranges(struct pathspec *pathspec,
760764
{
761765
struct line_log_data *r;
762766
struct strvec array = STRVEC_INIT;
763-
const char **paths;
764767

765768
for (r = range; r; r = r->next)
766769
strvec_push(&array, r->path);
767-
paths = strvec_detach(&array);
768770

769-
parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", paths);
770-
/* strings are now owned by pathspec */
771-
free(paths);
771+
parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", array.v);
772+
773+
strvec_clear(&array);
772774
}
773775

774776
void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args)
@@ -781,6 +783,8 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
781783
add_line_range(rev, commit, range);
782784

783785
parse_pathspec_from_ranges(&rev->diffopt.pathspec, range);
786+
787+
free_line_log_data(range);
784788
}
785789

786790
static void move_diff_queue(struct diff_queue_struct *dst,
@@ -1131,10 +1135,18 @@ static int process_all_files(struct line_log_data **range_out,
11311135
while (rg && strcmp(rg->path, pair->two->path))
11321136
rg = rg->next;
11331137
assert(rg);
1138+
if (rg->pair)
1139+
diff_free_filepair(rg->pair);
11341140
rg->pair = diff_filepair_dup(queue->queue[i]);
1141+
diff_ranges_release(&rg->diff);
11351142
memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges));
1143+
FREE_AND_NULL(pairdiff);
1144+
}
1145+
1146+
if (pairdiff) {
1147+
diff_ranges_release(pairdiff);
1148+
free(pairdiff);
11361149
}
1137-
free(pairdiff);
11381150
}
11391151

11401152
return changed;
@@ -1212,12 +1224,13 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
12121224
struct commit_list *p;
12131225
int i;
12141226
int nparents = commit_list_count(commit->parents);
1227+
int ret;
12151228

12161229
if (nparents > 1 && rev->first_parent_only)
12171230
nparents = 1;
12181231

12191232
ALLOC_ARRAY(diffqueues, nparents);
1220-
ALLOC_ARRAY(cand, nparents);
1233+
CALLOC_ARRAY(cand, nparents);
12211234
ALLOC_ARRAY(parents, nparents);
12221235

12231236
p = commit->parents;
@@ -1229,40 +1242,43 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
12291242

12301243
for (i = 0; i < nparents; i++) {
12311244
int changed;
1232-
cand[i] = NULL;
12331245
changed = process_all_files(&cand[i], rev, &diffqueues[i], range);
12341246
if (!changed) {
12351247
/*
12361248
* This parent can take all the blame, so we
12371249
* don't follow any other path in history
12381250
*/
12391251
add_line_range(rev, parents[i], cand[i]);
1240-
clear_commit_line_range(rev, commit);
12411252
commit_list_append(parents[i], &commit->parents);
1242-
free(parents);
1243-
free(cand);
1244-
free_diffqueues(nparents, diffqueues);
1245-
/* NEEDSWORK leaking like a sieve */
1246-
return 0;
1253+
1254+
ret = 0;
1255+
goto out;
12471256
}
12481257
}
12491258

12501259
/*
12511260
* No single parent took the blame. We add the candidates
12521261
* from the above loop to the parents.
12531262
*/
1254-
for (i = 0; i < nparents; i++) {
1263+
for (i = 0; i < nparents; i++)
12551264
add_line_range(rev, parents[i], cand[i]);
1256-
}
12571265

1266+
ret = 1;
1267+
1268+
out:
12581269
clear_commit_line_range(rev, commit);
12591270
free(parents);
1271+
for (i = 0; i < nparents; i++) {
1272+
if (!cand[i])
1273+
continue;
1274+
line_log_data_clear(cand[i]);
1275+
free(cand[i]);
1276+
}
12601277
free(cand);
12611278
free_diffqueues(nparents, diffqueues);
1262-
return 1;
1279+
return ret;
12631280

12641281
/* NEEDSWORK evil merge detection stuff */
1265-
/* NEEDSWORK leaking like a sieve */
12661282
}
12671283

12681284
int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit *commit)

0 commit comments

Comments
 (0)