about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--stdio-common/Makefile3
-rw-r--r--stdio-common/vfprintf.c31
3 files changed, 40 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 9d8c1155b5..11dcb3e071 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2000-09-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* stdio-common/vfprintf.c (process_string_arg): Handle precision
+	in wide char case correctly.  Don't allocate too long temporary
+	strings with alloca.
+
+	* stdio-common/Makefile (tests): Add tst-swprintf.
+	(tst-swprintf-ENV): New variable.
+	* stdio-common/tst-swprintf.c: New file.
+
 2000-09-05  Andreas Jaeger  <aj@suse.de>
 
 	* sysdeps/unix/sysv/linux/mips/bits/stat.h: Use st_pad5.
@@ -35,8 +45,8 @@
 	* soft-fp/sysdeps/sparc/sparc64/Makefile: Move from here...
 	* sysdeps/sparc/sparc64/soft-fp/Makefile: ... to here.
 
-        * soft-fp/sysdeps/sparc/sparc64/qp_neg.S: Move from here...
-        * sysdeps/sparc/sparc64/soft-fp/qp_neg.S: ... to here.
+	* soft-fp/sysdeps/sparc/sparc64/qp_neg.S: Move from here...
+	* sysdeps/sparc/sparc64/soft-fp/qp_neg.S: ... to here.
 
 	* soft-fp/sysdeps/powerpc/q_add.c: Move from here...
 	* sysdeps/powerpc/soft-fp/q_add.c: ... to here.
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 33907ebb60..7e78d44f97 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -54,7 +54,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
 	 bug1 bug2 bug3 bug4 bug5 bug6 bug7 bug8 bug9 bug10 bug11 bug12 bug13 \
 	 tfformat tiformat tllformat tstdiomisc tst-printfsz tst-wc-printf \
 	 scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \
-	 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf
+	 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf tst-swprintf
 
 test-srcs = tst-unbputc tst-printf
 
@@ -81,6 +81,7 @@ CFLAGS-scanf7.c = -Wno-format
 CFLAGS-tst-printfsz.c = -Wno-format
 
 tst-sscanf-ENV = LOCPATH=$(common-objpfx)localedata
+tst-swprintf-ENV = LOCPATH=$(common-objpfx)localedata
 
 $(inst_includedir)/bits/stdio_lim.h: $(common-objpfx)bits/stdio_lim.h
 	$(do-install)
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index b90f26f7fa..6219d795f8 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -995,6 +995,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
     LABEL (form_string):						      \
       {									      \
 	size_t len;							      \
+	int string_malloced;						      \
 									      \
 	/* The string argument could in fact be `char *' or `wchar_t *'.      \
 	   But this should not make a difference here.  */		      \
@@ -1006,6 +1007,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	/* Entry point for printing other strings.  */			      \
       LABEL (print_string):						      \
 									      \
+	string_malloced = 0;						      \
 	if (string == NULL)						      \
 	  {								      \
 	    /* Write "(null)" if there's space.  */			      \
@@ -1028,14 +1030,19 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    const char *mbs = (const char *) string;			      \
 	    mbstate_t mbstate;						      \
 									      \
-	    len = prec != -1 ? strnlen (mbs, prec) : strlen (mbs);	      \
+	    len = prec != -1 ? prec : strlen (mbs);			      \
 									      \
 	    /* Allocate dynamically an array which definitely is long	      \
 	       enough for the wide character version.  */		      \
-	    string = (CHAR_T *) alloca (len * sizeof (wchar_t));	      \
+	    if (len < 8192						      \
+		|| ((string = (CHAR_T *) malloc (len * sizeof (wchar_t)))     \
+		    == NULL))						      \
+	      string = (CHAR_T *) alloca (len * sizeof (wchar_t));	      \
+	    else							      \
+	      string_malloced = 1;					      \
 									      \
 	    memset (&mbstate, '\0', sizeof (mbstate_t));		      \
-	    len = __mbsnrtowcs (string, &mbs, len, len, &mbstate);	      \
+	    len = __mbsrtowcs (string, &mbs, len, &mbstate);		      \
 	    if (len == (size_t) -1)					      \
 	      {								      \
 		/* Illegal multibyte character.  */			      \
@@ -1064,6 +1071,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	outstring (string, len);					      \
 	if (left)							      \
 	  PAD (L' ');							      \
+	if (string_malloced)						      \
+	  free (string);						      \
       }									      \
       break;
 #else
@@ -1112,6 +1121,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
     LABEL (form_string):						      \
       {									      \
 	size_t len;							      \
+	int string_malloced;						      \
 									      \
 	/* The string argument could in fact be `char *' or `wchar_t *'.      \
 	   But this should not make a difference here.  */		      \
@@ -1123,6 +1133,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	/* Entry point for printing other strings.  */			      \
       LABEL (print_string):						      \
 									      \
+	string_malloced = 0;						      \
 	if (string == NULL)						      \
 	  {								      \
 	    /* Write "(null)" if there's space.  */			      \
@@ -1181,7 +1192,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	    if (prec > 0)						      \
 	      {								      \
 		/* The string `s2' might not be NUL terminated.  */	      \
-		string = (char *) alloca (prec);			      \
+		if (prec < 32768					      \
+		    || (string = (char *) malloc (prec)) == NULL)	      \
+		  string = (char *) alloca (prec);			      \
+		else							      \
+		  string_malloced = 1;					      \
 		len = __wcsrtombs (string, &s2, prec, &mbstate);	      \
 	      }								      \
 	    else							      \
@@ -1191,7 +1206,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 		  {							      \
 		    assert (__mbsinit (&mbstate));			      \
 		    s2 = (const wchar_t *) string;			      \
-		    string = (char *) alloca (len + 1);			      \
+		    if (len + 1 < 32768					      \
+			|| (string = (char *) malloc (len + 1)) == NULL)      \
+		      string = (char *) alloca (len + 1);		      \
+		    else						      \
+		      string_malloced = 1;				      \
 		    (void) __wcsrtombs (string, &s2, len + 1, &mbstate);      \
 		  }							      \
 	      }								      \
@@ -1215,6 +1234,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
 	outstring (string, len);					      \
 	if (left)							      \
 	  PAD (' ');							      \
+	if (string_malloced)						      \
+	  free (string);						      \
       }									      \
       break;
 #endif