public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: libc-alpha@sourceware.org
Subject: Re: Fix memory leak in __printf_fp_l (bug 26215)
Date: Thu, 9 Jul 2020 18:04:08 -0300	[thread overview]
Message-ID: <31f4ebeb-2ba5-d232-5905-235bc18b36be@linaro.org> (raw)
In-Reply-To: <alpine.DEB.2.21.2007091806270.14941@digraph.polyomino.org.uk>



On 09/07/2020 15:07, Joseph Myers wrote:
> __printf_fp_l has a memory leak in the case of some I/O errors, where
> both buffer and wbuffer have been malloced but the handling of I/O
> errors only frees wbuffer.  This patch fixes this by moving the
> declaration of buffer to an outer scope and ensuring that it is freed
> when wbuffer is freed.
> 
> Tested for x86_64 and x86.

LGTM, thanks.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

> 
> ---
> 
> This patch is relative to a tree with my previous fix for bug 26214
> <https://sourceware.org/pipermail/libc-alpha/2020-July/116043.html>
> (pending review) applied.
> 
> diff --git a/stdio-common/Makefile b/stdio-common/Makefile
> index dc3fd38a19..8475fd1f09 100644
> --- a/stdio-common/Makefile
> +++ b/stdio-common/Makefile
> @@ -68,7 +68,8 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
>  	 scanf14a scanf16a \
>  	 tst-printf-bz25691 \
>  	 tst-vfprintf-width-prec-alloc \
> -	 tst-printf-fp-free
> +	 tst-printf-fp-free \
> +	 tst-printf-fp-leak
>  
>  
>  test-srcs = tst-unbputc tst-printf tst-printfsz-islongdouble

Ok.

> @@ -80,12 +81,14 @@ tests-special += $(objpfx)tst-unbputc.out $(objpfx)tst-printf.out \
>  		 $(objpfx)tst-vfprintf-width-prec-mem.out \
>  		 $(objpfx)tst-printfsz-islongdouble.out \
>  		 $(objpfx)tst-printf-bz25691-mem.out \
> -		 $(objpfx)tst-printf-fp-free-mem.out
> +		 $(objpfx)tst-printf-fp-free-mem.out \
> +		 $(objpfx)tst-printf-fp-leak-mem.out
>  generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \
>  	     tst-printf-bz18872-mem.out \
>  	     tst-vfprintf-width-prec.mtrace tst-vfprintf-width-prec-mem.out \
>  	     tst-printf-bz25691.mtrace tst-printf-bz25691-mem.out \
> -	     tst-printf-fp-free.mtrace tst-printf-fp-free-mem.out
> +	     tst-printf-fp-free.mtrace tst-printf-fp-free-mem.out \
> +	     tst-printf-fp-leak.mtrace tst-printf-fp-leak-mem.out
>  endif
>  
>  tests-special += $(objpfx)tst-errno-manual.out
> @@ -113,6 +116,8 @@ tst-printf-bz25691-ENV = \
>    MALLOC_TRACE=$(objpfx)tst-printf-bz25691.mtrace
>  tst-printf-fp-free-ENV = \
>    MALLOC_TRACE=$(objpfx)tst-printf-fp-free.mtrace
> +tst-printf-fp-leak-ENV = \
> +  MALLOC_TRACE=$(objpfx)tst-printf-fp-leak.mtrace
>  
>  $(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
>  	$(SHELL) $< $(common-objpfx) '$(test-program-prefix)' > $@; \

Ok.

> diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
> index 49c693575e..c0b79f2184 100644
> --- a/stdio-common/printf_fp.c
> +++ b/stdio-common/printf_fp.c
> @@ -72,7 +72,10 @@
>        if (putc (outc, fp) == EOF)					      \
>  	{								      \
>  	  if (buffer_malloced)						      \
> -	    free (wbuffer);						      \
> +	    {								      \
> +	      free (buffer);						      \
> +	      free (wbuffer);						      \
> +	    }								      \
>  	  return -1;							      \
>  	}								      \
>        ++done;								      \
> @@ -87,7 +90,10 @@
>  	  if (PUT (fp, wide ? (const char *) wptr : ptr, outlen) != outlen)   \
>  	    {								      \
>  	      if (buffer_malloced)					      \
> -		free (wbuffer);						      \
> +		{							      \
> +		  free (buffer);					      \
> +		  free (wbuffer);					      \
> +		}							      \
>  	      return -1;						      \
>  	    }								      \
>  	  ptr += outlen;						      \
> @@ -110,7 +116,10 @@
>        if (PAD (fp, ch, len) != len)					      \
>  	{								      \
>  	  if (buffer_malloced)						      \
> -	    free (wbuffer);						      \
> +	    {								      \
> +	      free (buffer);						      \
> +	      free (wbuffer);						      \
> +	    }								      \
>  	  return -1;							      \
>  	}								      \
>        done += len;							      \

Ok.

> @@ -259,7 +268,8 @@ __printf_fp_l (FILE *fp, locale_t loc,
>  
>    /* Buffer in which we produce the output.  */
>    wchar_t *wbuffer = NULL;
> -  /* Flag whether wbuffer is malloc'ed or not.  */
> +  char *buffer = NULL;
> +  /* Flag whether wbuffer and buffer are malloc'ed or not.  */
>    int buffer_malloced = 0;
>  
>    p.expsign = 0;
> @@ -1172,7 +1182,6 @@ __printf_fp_l (FILE *fp, locale_t loc,
>        PADN ('0', width);
>  
>      {
> -      char *buffer = NULL;
>        char *buffer_end = NULL;
>        char *cp = NULL;
>        char *tmpptr;
> @@ -1252,6 +1261,7 @@ __printf_fp_l (FILE *fp, locale_t loc,
>  	  free (wbuffer);
>  	  /* Avoid a double free if the subsequent PADN encounters an
>  	     I/O error.  */
> +	  buffer = NULL;
>  	  wbuffer = NULL;
>  	}
>      }

Ok.

> diff --git a/stdio-common/tst-printf-fp-leak.c b/stdio-common/tst-printf-fp-leak.c
> new file mode 100644
> index 0000000000..da11a486dd
> --- /dev/null
> +++ b/stdio-common/tst-printf-fp-leak.c
> @@ -0,0 +1,34 @@
> +/* Test memory leak in __printf_fp_l (bug 26215).
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <mcheck.h>
> +#include <stdio.h>
> +#include <support/check.h>
> +
> +static int
> +do_test (void)
> +{
> +  mtrace ();
> +  FILE *fp = fopen ("/dev/full", "w");
> +  TEST_VERIFY_EXIT (fp != NULL);
> +  TEST_COMPARE (fprintf (fp, "%.65536f", 1.0), -1);
> +  fclose (fp);
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> 

Ok.

  reply	other threads:[~2020-07-09 21:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-09 18:07 Joseph Myers
2020-07-09 21:04 ` Adhemerval Zanella [this message]
2020-07-10  7:20 ` Florian Weimer
2020-07-10 15:03   ` Joseph Myers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=31f4ebeb-2ba5-d232-5905-235bc18b36be@linaro.org \
    --to=adhemerval.zanella@linaro.org \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).