vfprintf: Rewrite printf_positional to use struct scratch_buffer
This commit is contained in:
parent
52fb79d6cd
commit
db8ad8fac3
@ -1,3 +1,8 @@
|
||||
2015-10-17 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* stdio-common/vfprintf.c (printf_positional): Rewrite to use
|
||||
struct scratch_buffer instead of extend_alloca.
|
||||
|
||||
2015-10-17 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* sysdeps/unix/sysv/linux/kernel-features.h
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user