On Tue, Aug 13, 2024 at 09:55:10AM -0700, Junio C Hamano wrote: > Patrick Steinhardt <ps@xxxxxx> writes: > > > There are various memory leaks hit by git-format-patch(1). Basically all > > of them are trivial, except that un-setting `diffopt.no_free` requires > > us to unset the `diffopt.file` because we manually close it already. > > > > Signed-off-by: Patrick Steinhardt <ps@xxxxxx> > > --- > > builtin/log.c | 12 +++++++++--- > > t/t4014-format-patch.sh | 1 + > > 2 files changed, 10 insertions(+), 3 deletions(-) > > > > diff --git a/builtin/log.c b/builtin/log.c > > index a73a767606..ff997a0d0e 100644 > > --- a/builtin/log.c > > +++ b/builtin/log.c > > @@ -1833,6 +1833,7 @@ static struct commit *get_base_commit(const struct format_config *cfg, > > } > > > > rev[i] = merge_base->item; > > + free_commit_list(merge_base); > > } > > > > if (rev_nr % 2) > > This is correct, but isn't merge_base leaking when there are > multiple and we are not dying on failure? Perhaps something along > this line? Yes, good catch. > struct commit_list *merge_base = NULL; > if (repo_get_merge_bases(the_repository, > rev[2 * i], > rev[2 * i + 1], &merge_base) < 0 || > !merge_base || merge_base->next) { > if (die_on_failure) { > die(_("failed to find exact merge base")); > } else { > + free_commit_list(merge_base); > free(rev); > return NULL; > } > } > > > @@ -2548,12 +2550,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) > > else > > print_signature(signature, rev.diffopt.file); > > } > > - if (output_directory) > > + if (output_directory) { > > fclose(rev.diffopt.file); > > + rev.diffopt.file = NULL; > > Is this a leakfix, or just a general code hygiene improvement? Not a leak fix, but required because of the leak fix. As we now unset `rev.diffopt.no_free`, `release_revisions()` will call `diff_free()` and try to close the file pointer. But as we already did, it would cause a segfault as we now try to close it twice. Patrick