threads / patch / 42288

patch, 2 partsam: plug small memory leak when split_mail_stgit_series() fails

Subject: [PATCH 1/2] am: plug small memory leak when split_mail_stgit_series() fails

## tl;dr

8 messages between May 11, 2016 and May 12, 2016. Diffs are folded; open one to read it.

replies: 7people: 4as markdown or json

Junio C Hamano· May 11, 2016, 23:35 UTC · lore
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/am.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
Show changes to builtin/am.c +3 −1
diff --git a/builtin/am.c b/builtin/am.c
index ec75906..f1a84c6 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -842,9 +842,11 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
 	series_dir = dirname(series_dir_buf);
 
 	fp = fopen(*paths, "r");
-	if (!fp)
+	if (!fp) {
+		free(series_dir_buf);
 		return error(_("could not open '%s' for reading: %s"), *paths,
 				strerror(errno));
+	}
 
 	while (!strbuf_getline(&sb, fp, '\n')) {
 		if (*sb.buf == '#')
-- 
2.8.2-679-g91c6421
Junio C Hamano· May 11, 2016, 23:35 UTC · re: Junio C Hamano · lore

[PATCH 2/2] am: plug FILE * leak in split_mail_conv()

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/am.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
Show changes to builtin/am.c +3 −1
diff --git a/builtin/am.c b/builtin/am.c
index f1a84c6..a373928 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -761,9 +761,11 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
 		mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
 
 		out = fopen(mail, "w");
-		if (!out)
+		if (!out) {
+			fclose(in);
 			return error(_("could not open '%s' for writing: %s"),
 					mail, strerror(errno));
+		}
 
 		ret = fn(out, in, keep_cr);
 
-- 
2.8.2-679-g91c6421
Jeff King· May 12, 2016, 04:47 UTC · re: Junio C Hamano · lore

Re: [PATCH 2/2] am: plug FILE * leak in split_mail_conv()

On Wed, May 11, 2016 at 04:35:46PM -0700, Junio C Hamano wrote:
Show 19 quoted lines
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>  builtin/am.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/builtin/am.c b/builtin/am.c
> index f1a84c6..a373928 100644
> --- a/builtin/am.c
> +++ b/builtin/am.c
> @@ -761,9 +761,11 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
>  		mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
>  
>  		out = fopen(mail, "w");
> -		if (!out)
> +		if (!out) {
> +			fclose(in);
>  			return error(_("could not open '%s' for writing: %s"),
>  					mail, strerror(errno));
> +		}

Presumably `fclose` doesn't ever overwrite errno in practice, but I guess it could in theory.

I also found it weird that we might fclose(stdin) via this line, but that matches what happens in the non-error path, so I guess it's OK?

-Peff
Mikael Magnusson· May 12, 2016, 05:23 UTC · re: Jeff King · lore

Re: [PATCH 2/2] am: plug FILE * leak in split_mail_conv()

On Thu, May 12, 2016 at 6:47 AM, Jeff King <peff@peff.net> wrote:
Show 24 quoted lines
> On Wed, May 11, 2016 at 04:35:46PM -0700, Junio C Hamano wrote:
>
>> Signed-off-by: Junio C Hamano <gitster@pobox.com>
>> ---
>>  builtin/am.c | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/builtin/am.c b/builtin/am.c
>> index f1a84c6..a373928 100644
>> --- a/builtin/am.c
>> +++ b/builtin/am.c
>> @@ -761,9 +761,11 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
>>               mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
>>
>>               out = fopen(mail, "w");
>> -             if (!out)
>> +             if (!out) {
>> +                     fclose(in);
>>                       return error(_("could not open '%s' for writing: %s"),
>>                                       mail, strerror(errno));
>> +             }
>
> Presumably `fclose` doesn't ever overwrite errno in practice, but I
> guess it could in theory.

It probably does pretty often in general, but not when the file is opened for input only.

-- 
Mikael Magnusson
Jeff King· May 12, 2016, 05:29 UTC · re: Mikael Magnusson · lore

Re: [PATCH 2/2] am: plug FILE * leak in split_mail_conv()

On Thu, May 12, 2016 at 07:23:02AM +0200, Mikael Magnusson wrote:
Show 12 quoted lines
> >> -             if (!out)
> >> +             if (!out) {
> >> +                     fclose(in);
> >>                       return error(_("could not open '%s' for writing: %s"),
> >>                                       mail, strerror(errno));
> >> +             }
> >
> > Presumably `fclose` doesn't ever overwrite errno in practice, but I
> > guess it could in theory.
> 
> It probably does pretty often in general, but not when the file is
> opened for input only.
Right, I should have said "this fclose".

I think EBADF is the only likely error when closing input, and that's presumably impossible here.

-Peff
Eric Wong· May 12, 2016, 07:59 UTC · re: Jeff King · lore

Re: [PATCH 2/2] am: plug FILE * leak in split_mail_conv()

Jeff King <peff@peff.net> wrote:
Show 15 quoted lines
> On Wed, May 11, 2016 at 04:35:46PM -0700, Junio C Hamano wrote:
> > +++ b/builtin/am.c
> > @@ -761,9 +761,11 @@ static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
> >  		mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
> >  
> >  		out = fopen(mail, "w");
> > -		if (!out)
> > +		if (!out) {
> > +			fclose(in);
> >  			return error(_("could not open '%s' for writing: %s"),
> >  					mail, strerror(errno));
> > +		}
> 
> Presumably `fclose` doesn't ever overwrite errno in practice, but I
> guess it could in theory.

I think both patches in this series would benefit from capturing errno before cleanup. `fclose` can call `free`, and `free` could do any manner of things such as calling `madvise` with a flag not implemented in the running kernel, or failing an optional trylock without being fatal.

There's lots of non-standard malloc implementations out there :)

So I'm not sure if there's ever a guarantee that a non-error function call preserves `errno`.

Jeff King· May 12, 2016, 08:03 UTC · re: Eric Wong · lore

Re: [PATCH 2/2] am: plug FILE * leak in split_mail_conv()

On Thu, May 12, 2016 at 07:59:39AM +0000, Eric Wong wrote:
Show 10 quoted lines
> I think both patches in this series would benefit from capturing
> errno before cleanup.  `fclose` can call `free`, and `free` could
> do any manner of things such as calling `madvise` with a flag
> not implemented in the running kernel, or failing an optional
> trylock without being fatal.
> 
> There's lots of non-standard malloc implementations out there :)
> 
> So I'm not sure if there's ever a guarantee that a non-error
> function call preserves `errno`.
Good point. This came up not too long ago in:
  http://article.gmane.org/gmane.comp.version-control.git/286460

I believe POSIX does say that non-error calls should preserve errno, but all the world is not POSIX. And a future POSIX will mandate that `free` should not touch errno, but it's not the future yet (and also, all the world's not POSIX).

-Peff
Junio C Hamano· May 12, 2016, 15:59 UTC · re: Jeff King · lore

Re: [PATCH 2/2] am: plug FILE * leak in split_mail_conv()

Jeff King <peff@peff.net> writes:
> Presumably `fclose` doesn't ever overwrite errno in practice, but I
> guess it could in theory.
Yeah, these two patches share the same issue.

← back to recent threads