Re: [PATCH v3 18/22] builtin/format-patch: fix various trivial memory leaks
- From
Patrick Steinhardt <ps@pks.im>
- Date
- Aug 14, 2024, 04:56 UTC
- Message-ID
- <Zrw47_cAtpVZ0Inh@tanuki>
- In-Reply-To
- <xmqqed6s747l.fsf@gitster.g>
On Tue, Aug 13, 2024 at 09:55:10AM -0700, Junio C Hamano wrote:
Show 28 quoted lines
> Patrick Steinhardt <ps@pks.im> 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@pks.im> > > --- > > 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.
Show 24 quoted lines
> 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