diff options
author | Ulrich Drepper <drepper@redhat.com> | 1999-02-23 15:27:54 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 1999-02-23 15:27:54 +0000 |
commit | afe426a038512b1b7a9477eb905ab4523a1e1f85 (patch) | |
tree | 283956814f182aabcd6e716b1ecdd2e3f33994a6 /stdio-common/vfprintf.c | |
parent | 4985fb53859f7aab18676cdaeb7a620571269976 (diff) | |
download | glibc-afe426a038512b1b7a9477eb905ab4523a1e1f85.tar glibc-afe426a038512b1b7a9477eb905ab4523a1e1f85.tar.gz glibc-afe426a038512b1b7a9477eb905ab4523a1e1f85.tar.bz2 glibc-afe426a038512b1b7a9477eb905ab4523a1e1f85.zip |
Update.
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]
Diffstat (limited to 'stdio-common/vfprintf.c')
-rw-r--r-- | stdio-common/vfprintf.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index d9cd620853..b61b637af9 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -227,7 +227,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) /* Buffer intermediate results. */ char work_buffer[1000]; -#define workend (&work_buffer[sizeof (work_buffer) - 1]) + char *workend; /* State for restartable multibyte character handling functions. */ mbstate_t mbstate; @@ -1084,6 +1084,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) char pad = ' '; /* Padding character. */ CHAR_T spec; + workend = &work_buffer[sizeof (work_buffer) - 1]; + /* Get current character in format string. */ JUMP (*++f, step0_jumps); @@ -1157,12 +1159,22 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) pad = L_(' '); 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); /* Given width in format string. */ LABEL (width): 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_('$')) /* Oh, oh. The argument comes from a positional parameter. */ goto do_positional; @@ -1189,6 +1201,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) prec = read_int (&f); else prec = 0; + if (prec > width && prec + 32 > sizeof (work_buffer)) + workend = alloca (spec + 32) + (spec + 31); JUMP (*f, step2_jumps); /* Process 'h' modifier. There might another 'h' following. */ @@ -1471,6 +1485,10 @@ do_positional: 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. */ while (1) { @@ -1558,7 +1576,8 @@ printf_unknown (FILE *s, const struct printf_info *info, { 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; outchar ('%'); |