From 90663e9c814a919fa1fb41a878c06ef2fae58ed2 Mon Sep 17 00:00:00 2001
From: Joseph Myers <joseph@codesourcery.com>
Date: Thu, 9 Jul 2020 21:52:24 +0000
Subject: [PATCH] Fix memory leak in __printf_fp_l (bug 26215).

__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.

note that this patch is parts of the origin one.

Tested for x86_64 and x86.
---
 stdio-common/printf_fp.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index c310eb8e..b88e9cc6 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;							      \
@@ -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;
 	}
     }
-- 
2.23.0

