Skip to content

Commit a90a089

Browse files
pks-tgitster
authored andcommitted
revision: free diff options
There is a todo comment in `release_revisions()` that mentions that we need to free the diff options, which was added via 54c8a7c (revisions API: add a TODO for diff_free(&revs->diffopt), 2022-04-14). Releasing the diff options wasn't quite feasible at that time because some call sites rely on its contents to remain even after the revisions have been released. In fact, there really only are a couple of callsites that misbehave here: - `cmd_shortlog()` releases the revisions, but continues to access its file pointer. - `do_diff_cache()` creates a shallow copy of `struct diff_options`, but does not set the `no_free` member. Consequently, we end up releasing resources of the caller-provided diff options. - `diff_free()` and friends do not play nice when being called multiple times as they don't unset data structures that they have just released. Fix all of those cases and enable the call to `diff_free()`, which plugs a bunch of memory leaks. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a282dbe commit a90a089

11 files changed

+17
-7
lines changed

builtin/shortlog.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,8 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
460460
else
461461
get_from_rev(&rev, &log);
462462

463-
release_revisions(&rev);
464-
465463
shortlog_output(&log);
466-
if (log.file != stdout)
467-
fclose(log.file);
464+
release_revisions(&rev);
468465
return 0;
469466
}
470467

diff-lib.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,11 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
662662
repo_init_revisions(opt->repo, &revs, NULL);
663663
copy_pathspec(&revs.prune_data, &opt->pathspec);
664664
revs.diffopt = *opt;
665+
revs.diffopt.no_free = 1;
665666

666667
if (diff_cache(&revs, tree_oid, NULL, 1))
667668
exit(128);
669+
668670
release_revisions(&revs);
669671
return 0;
670672
}

diff.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6649,8 +6649,10 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
66496649

66506650
static void diff_free_file(struct diff_options *options)
66516651
{
6652-
if (options->close_file)
6652+
if (options->close_file && options->file) {
66536653
fclose(options->file);
6654+
options->file = NULL;
6655+
}
66546656
}
66556657

66566658
static void diff_free_ignore_regex(struct diff_options *options)
@@ -6661,7 +6663,9 @@ static void diff_free_ignore_regex(struct diff_options *options)
66616663
regfree(options->ignore_regex[i]);
66626664
free(options->ignore_regex[i]);
66636665
}
6664-
free(options->ignore_regex);
6666+
6667+
FREE_AND_NULL(options->ignore_regex);
6668+
options->ignore_regex_nr = 0;
66656669
}
66666670

66676671
void diff_free(struct diff_options *options)

revision.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3191,7 +3191,7 @@ void release_revisions(struct rev_info *revs)
31913191
release_revisions_mailmap(revs->mailmap);
31923192
free_grep_patterns(&revs->grep_filter);
31933193
graph_clear(revs->graph);
3194-
/* TODO (need to handle "no_free"): diff_free(&revs->diffopt) */
3194+
diff_free(&revs->diffopt);
31953195
diff_free(&revs->pruning);
31963196
reflog_walk_info_release(revs->reflog_info);
31973197
release_revisions_topo_walk_info(revs->topo_walk_info);

t/t4208-log-magic-pathspec.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='magic pathspec tests using git-log'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910

1011
test_expect_success 'setup' '

t/t6000-rev-list-misc.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='miscellaneous rev-list tests'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910

1011
test_expect_success setup '

t/t6001-rev-list-graft.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='Revision traversal vs grafts and path limiter'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910

1011
test_expect_success setup '

t/t6013-rev-list-reverse-parents.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ test_description='--reverse combines with --parents'
55
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
66
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
77

8+
TEST_PASSES_SANITIZE_LEAK=true
89
. ./test-lib.sh
910

1011

t/t6017-rev-list-stdin.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ test_description='log family learns --stdin'
88
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
99
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
1010

11+
TEST_PASSES_SANITIZE_LEAK=true
1112
. ./test-lib.sh
1213

1314
check () {

t/t9500-gitweb-standalone-no-errors.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ or warnings to log.'
1313
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
1414
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
1515

16+
TEST_PASSES_SANITIZE_LEAK=true
1617
. ./lib-gitweb.sh
1718

1819
# ----------------------------------------------------------------------

0 commit comments

Comments
 (0)