diff mbox

[v2] vfprintf: Rewrite printf_positional to use struct scratch_buffer

Message ID 561FC4BC.5040304@redhat.com
State New
Headers show

Commit Message

Florian Weimer Oct. 15, 2015, 3:22 p.m. UTC
This rebase picks up the specs_malloced/args_malloced fix in commit
560b04462f899e76a0062ec89422caa6e94fd67f.

Florian

Comments

Mike Frysinger Oct. 17, 2015, 3:27 a.m. UTC | #1
On 15 Oct 2015 17:22, Florian Weimer wrote:
> This rebase picks up the specs_malloced/args_malloced fix in commit
> 560b04462f899e76a0062ec89422caa6e94fd67f.

looks good.  i like this new api :).
-mike
diff mbox

Patch

2015-10-15  Florian Weimer  <fweimer@redhat.com>

	* stdio-common/vfprintf.c (printf_positional): Rewrite to use
	struct scratch_buffer instead of extend_alloca.

diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index 5e408d2..ae01452 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -29,6 +29,7 @@ 
 #include <_itoa.h>
 #include <locale/localeinfo.h>
 #include <stdio.h>
+#include <scratch_buffer.h>
 
 /* This code is shared between the standard stdio implementation found
    in GNU C library and the libio implementation originally found in
@@ -1698,18 +1699,15 @@  printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
   void *args_malloced = NULL;
 
   /* For positional argument handling.  */
-  struct printf_spec *specs;
-
-  /* Track if we malloced the SPECS array and thus must free it.  */
-  bool specs_malloced = false;
+  struct scratch_buffer specsbuf;
+  scratch_buffer_init (&specsbuf);
+  struct printf_spec *specs = specsbuf.data;
+  size_t specs_limit = specsbuf.length / sizeof (specs[0]);
 
   /* Array with information about the needed arguments.  This has to
      be dynamically extensible.  */
   size_t nspecs = 0;
-  /* A more or less arbitrary start value.  */
-  size_t nspecs_size = 32 * sizeof (struct printf_spec);
 
-  specs = alloca (nspecs_size);
   /* The number of arguments the format string requests.  This will
      determine the size of the array needed to store the argument
      attributes.  */
@@ -1746,42 +1744,15 @@  printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
   for (const UCHAR_T *f = lead_str_end; *f != L_('\0');
        f = specs[nspecs++].next_fmt)
     {
-      if (nspecs * sizeof (*specs) >= nspecs_size)
+      if (nspecs == specs_limit)
 	{
-	  /* Extend the array of format specifiers.  */
-	  if (nspecs_size * 2 < nspecs_size)
+	  if (!scratch_buffer_grow_preserve (&specsbuf))
 	    {
-	      __set_errno (ENOMEM);
 	      done = -1;
 	      goto all_done;
 	    }
-	  struct printf_spec *old = specs;
-	  if (__libc_use_alloca (2 * nspecs_size))
-	    specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
-	  else
-	    {
-	      nspecs_size *= 2;
-	      specs = malloc (nspecs_size);
-	      if (specs == NULL)
-		{
-		  __set_errno (ENOMEM);
-		  specs = old;
-		  done = -1;
-		  goto all_done;
-		}
-	    }
-
-	  /* Copy the old array's elements to the new space.  */
-	  memmove (specs, old, nspecs * sizeof (*specs));
-
-	  /* If we had previously malloc'd space for SPECS, then
-	     release it after the copy is complete.  */
-	  if (specs_malloced)
-	    free (old);
-
-	  /* Now set SPECS_MALLOCED if needed.  */
-	  if (!__libc_use_alloca (nspecs_size))
-	    specs_malloced = true;
+	  specs = specsbuf.data;
+	  specs_limit = specsbuf.length / sizeof (specs[0]);
 	}
 
       /* Parse the format specifier.  */
@@ -2091,12 +2062,11 @@  printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
 		 - specs[nspecs_done].end_of_fmt);
     }
  all_done:
-  if (__glibc_unlikely (specs_malloced))
-    free (specs);
   if (__glibc_unlikely (args_malloced != NULL))
     free (args_malloced);
   if (__glibc_unlikely (workstart != NULL))
     free (workstart);
+  scratch_buffer_free (&specsbuf);
   return done;
 }