1999-02-23  Ulrich Drepper  <drepper@cygnus.com>

	* stdio-common/vfprintf.c (vfprintf): If precision or width if too
	large for work_buffer, allocate new buffer.
	(printf_unknown): Likewise.  [PR libc/988]
This commit is contained in:
Ulrich Drepper 1999-02-23 15:27:54 +00:00
parent 4985fb5385
commit afe426a038
2 changed files with 27 additions and 2 deletions

View File

@ -1,3 +1,9 @@
1999-02-23 Ulrich Drepper <drepper@cygnus.com>
* stdio-common/vfprintf.c (vfprintf): If precision or width if too
large for work_buffer, allocate new buffer.
(printf_unknown): Likewise. [PR libc/988]
1999-02-22 Ulrich Drepper <drepper@cygnus.com> 1999-02-22 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/sysv/linux/ttyname.c: Use __xstat and __fxstat * sysdeps/unix/sysv/linux/ttyname.c: Use __xstat and __fxstat

View File

@ -227,7 +227,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
/* Buffer intermediate results. */ /* Buffer intermediate results. */
char work_buffer[1000]; char work_buffer[1000];
#define workend (&work_buffer[sizeof (work_buffer) - 1]) char *workend;
/* State for restartable multibyte character handling functions. */ /* State for restartable multibyte character handling functions. */
mbstate_t mbstate; mbstate_t mbstate;
@ -1084,6 +1084,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
char pad = ' '; /* Padding character. */ char pad = ' '; /* Padding character. */
CHAR_T spec; CHAR_T spec;
workend = &work_buffer[sizeof (work_buffer) - 1];
/* Get current character in format string. */ /* Get current character in format string. */
JUMP (*++f, step0_jumps); JUMP (*++f, step0_jumps);
@ -1157,12 +1159,22 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
pad = L_(' '); pad = L_(' ');
left = 1; left = 1;
} }
if (width + 32 >= sizeof (work_buffer))
/* We have to use a special buffer. The "32" is just a safe
bet for all the output which is not counted in the width. */
workend = alloca (width + 32) + (width + 31);
} }
JUMP (*f, step1_jumps); JUMP (*f, step1_jumps);
/* Given width in format string. */ /* Given width in format string. */
LABEL (width): LABEL (width):
width = read_int (&f); width = read_int (&f);
if (width + 32 >= sizeof (work_buffer))
/* We have to use a special buffer. The "32" is just a safe
bet for all the output which is not counted in the width. */
workend = alloca (width + 32) + (width + 31);
if (*f == L_('$')) if (*f == L_('$'))
/* Oh, oh. The argument comes from a positional parameter. */ /* Oh, oh. The argument comes from a positional parameter. */
goto do_positional; goto do_positional;
@ -1189,6 +1201,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
prec = read_int (&f); prec = read_int (&f);
else else
prec = 0; prec = 0;
if (prec > width && prec + 32 > sizeof (work_buffer))
workend = alloca (spec + 32) + (spec + 31);
JUMP (*f, step2_jumps); JUMP (*f, step2_jumps);
/* Process 'h' modifier. There might another 'h' following. */ /* Process 'h' modifier. There might another 'h' following. */
@ -1471,6 +1485,10 @@ do_positional:
prec = specs[nspecs_done].info.prec; prec = specs[nspecs_done].info.prec;
} }
/* Maybe the buffer is too small. */
if (MAX (prec, width) + 32 > sizeof (work_buffer))
workend = alloca (MAX (prec, width) + 32) + (MAX (prec, width) + 31);
/* Process format specifiers. */ /* Process format specifiers. */
while (1) while (1)
{ {
@ -1558,7 +1576,8 @@ printf_unknown (FILE *s, const struct printf_info *info,
{ {
int done = 0; int done = 0;
char work_buffer[BUFSIZ]; char work_buffer[MAX (info->width, info->spec) + 32];
char *const workend = &work_buffer[sizeof (work_buffer) - 1];
register char *w; register char *w;
outchar ('%'); outchar ('%');