vfprintf: Use struct scratch_buffer for positional arguments allocation
This commit is contained in:
parent
cd00e12d31
commit
12d5853e22
@ -1,3 +1,9 @@
|
|||||||
|
2017-06-29 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
* stdio-common/vfprintf.c (printf_positional): Use struct
|
||||||
|
scratch_buffer to allocate backing storage for the args_value,
|
||||||
|
args_size, args_type arrays.
|
||||||
|
|
||||||
2017-06-29 Florian Weimer <fweimer@redhat.com>
|
2017-06-29 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
* stdio-common/_i18n_number.h (_i18n_number_rewrite): Use struct
|
* stdio-common/_i18n_number.h (_i18n_number_rewrite): Use struct
|
||||||
|
@ -1708,15 +1708,17 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
|
|||||||
CHAR_T *work_buffer, int save_errno,
|
CHAR_T *work_buffer, int save_errno,
|
||||||
const char *grouping, THOUSANDS_SEP_T thousands_sep)
|
const char *grouping, THOUSANDS_SEP_T thousands_sep)
|
||||||
{
|
{
|
||||||
/* For the argument descriptions, which may be allocated on the heap. */
|
|
||||||
void *args_malloced = NULL;
|
|
||||||
|
|
||||||
/* For positional argument handling. */
|
/* For positional argument handling. */
|
||||||
struct scratch_buffer specsbuf;
|
struct scratch_buffer specsbuf;
|
||||||
scratch_buffer_init (&specsbuf);
|
scratch_buffer_init (&specsbuf);
|
||||||
struct printf_spec *specs = specsbuf.data;
|
struct printf_spec *specs = specsbuf.data;
|
||||||
size_t specs_limit = specsbuf.length / sizeof (specs[0]);
|
size_t specs_limit = specsbuf.length / sizeof (specs[0]);
|
||||||
|
|
||||||
|
/* Used as a backing store for args_value, args_size, args_type
|
||||||
|
below. */
|
||||||
|
struct scratch_buffer argsbuf;
|
||||||
|
scratch_buffer_init (&argsbuf);
|
||||||
|
|
||||||
/* Array with information about the needed arguments. This has to
|
/* Array with information about the needed arguments. This has to
|
||||||
be dynamically extensible. */
|
be dynamically extensible. */
|
||||||
size_t nspecs = 0;
|
size_t nspecs = 0;
|
||||||
@ -1725,10 +1727,6 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
|
|||||||
determine the size of the array needed to store the argument
|
determine the size of the array needed to store the argument
|
||||||
attributes. */
|
attributes. */
|
||||||
size_t nargs = 0;
|
size_t nargs = 0;
|
||||||
size_t bytes_per_arg;
|
|
||||||
union printf_arg *args_value;
|
|
||||||
int *args_size;
|
|
||||||
int *args_type;
|
|
||||||
|
|
||||||
/* Positional parameters refer to arguments directly. This could
|
/* Positional parameters refer to arguments directly. This could
|
||||||
also determine the maximum number of arguments. Track the
|
also determine the maximum number of arguments. Track the
|
||||||
@ -1778,38 +1776,29 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
|
|||||||
|
|
||||||
/* Determine the number of arguments the format string consumes. */
|
/* Determine the number of arguments the format string consumes. */
|
||||||
nargs = MAX (nargs, max_ref_arg);
|
nargs = MAX (nargs, max_ref_arg);
|
||||||
/* Calculate total size needed to represent a single argument across
|
|
||||||
all three argument-related arrays. */
|
|
||||||
bytes_per_arg = (sizeof (*args_value) + sizeof (*args_size)
|
|
||||||
+ sizeof (*args_type));
|
|
||||||
|
|
||||||
/* Check for potential integer overflow. */
|
union printf_arg *args_value;
|
||||||
if (__glibc_unlikely (nargs > INT_MAX / bytes_per_arg))
|
int *args_size;
|
||||||
{
|
int *args_type;
|
||||||
__set_errno (EOVERFLOW);
|
{
|
||||||
done = -1;
|
/* Calculate total size needed to represent a single argument
|
||||||
goto all_done;
|
across all three argument-related arrays. */
|
||||||
}
|
size_t bytes_per_arg
|
||||||
|
= sizeof (*args_value) + sizeof (*args_size) + sizeof (*args_type);
|
||||||
/* Allocate memory for all three argument arrays. */
|
if (!scratch_buffer_set_array_size (&argsbuf, nargs, bytes_per_arg))
|
||||||
if (__libc_use_alloca (nargs * bytes_per_arg))
|
{
|
||||||
args_value = alloca (nargs * bytes_per_arg);
|
done = -1;
|
||||||
else
|
goto all_done;
|
||||||
{
|
}
|
||||||
args_value = args_malloced = malloc (nargs * bytes_per_arg);
|
args_value = argsbuf.data;
|
||||||
if (args_value == NULL)
|
/* Set up the remaining two arrays to each point past the end of
|
||||||
{
|
the prior array, since space for all three has been allocated
|
||||||
done = -1;
|
now. */
|
||||||
goto all_done;
|
args_size = &args_value[nargs].pa_int;
|
||||||
}
|
args_type = &args_size[nargs];
|
||||||
}
|
memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
|
||||||
|
nargs * sizeof (*args_type));
|
||||||
/* Set up the remaining two arrays to each point past the end of the
|
}
|
||||||
prior array, since space for all three has been allocated now. */
|
|
||||||
args_size = &args_value[nargs].pa_int;
|
|
||||||
args_type = &args_size[nargs];
|
|
||||||
memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
|
|
||||||
nargs * sizeof (*args_type));
|
|
||||||
|
|
||||||
/* XXX Could do sanity check here: If any element in ARGS_TYPE is
|
/* XXX Could do sanity check here: If any element in ARGS_TYPE is
|
||||||
still zero after this loop, format is invalid. For now we
|
still zero after this loop, format is invalid. For now we
|
||||||
@ -2075,10 +2064,9 @@ printf_positional (_IO_FILE *s, const CHAR_T *format, int readonly_format,
|
|||||||
- specs[nspecs_done].end_of_fmt);
|
- specs[nspecs_done].end_of_fmt);
|
||||||
}
|
}
|
||||||
all_done:
|
all_done:
|
||||||
if (__glibc_unlikely (args_malloced != NULL))
|
|
||||||
free (args_malloced);
|
|
||||||
if (__glibc_unlikely (workstart != NULL))
|
if (__glibc_unlikely (workstart != NULL))
|
||||||
free (workstart);
|
free (workstart);
|
||||||
|
scratch_buffer_free (&argsbuf);
|
||||||
scratch_buffer_free (&specsbuf);
|
scratch_buffer_free (&specsbuf);
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user