summary refs log tree commit diff
path: root/stdio-common
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1999-02-23 15:27:54 +0000
committerUlrich Drepper <drepper@redhat.com>1999-02-23 15:27:54 +0000
commitafe426a038512b1b7a9477eb905ab4523a1e1f85 (patch)
tree283956814f182aabcd6e716b1ecdd2e3f33994a6 /stdio-common
parent4985fb53859f7aab18676cdaeb7a620571269976 (diff)
downloadglibc-afe426a038512b1b7a9477eb905ab4523a1e1f85.tar.gz
glibc-afe426a038512b1b7a9477eb905ab4523a1e1f85.tar.xz
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')
-rw-r--r--stdio-common/vfprintf.c23
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 ('%');