diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2008-01-07 22:01:04 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2008-01-07 22:01:04 +0000 |
commit | 377e904744fe30e5f1a5ad161b3e49774507bc5b (patch) | |
tree | dd85dab2ccd399e1204c9668833904d3992e20c1 | |
parent | d9009444ad8076fbcb3002d8ee6eb91193e5d9ec (diff) | |
download | eglibc2-377e904744fe30e5f1a5ad161b3e49774507bc5b.tar.gz |
Merge from FSF glibc-2_5-branch:
2007-05-21 Jakub Jelinek <jakub@redhat.com>
[BZ #4514]
* stdio-common/vfprintf.c (vfprintf): Don't shadow workstart variable,
reinitialize workend at the start of each do_positional format spec
loop, free workstart before do_positional loops.
(printf_unknown): Fix size of work_buffer.
* stdio-common/tst-sprintf.c (main): Add 3 new testcases.
2007-05-06 Ulrich Drepper <drepper@redhat.com>
* stdio-common/vfprintf.c (process_string_arg): Optimize
ridiculous precision in wide char code printing multi-byte string.
Reported by Jim Meyering <jim@meyering.net>.
2007-05-04 Ulrich Drepper <drepper@redhat.com>
* stdio-common/vfprintf.c (process_string_arg): Adjust call to
__mbsnrtowcs after last change.
2007-05-02 Jakub Jelinek <jakub@redhat.com>
* stdio-common/vfprintf.c (process_string_arg): Use a VLA rather than
fixed length array for ignore.
2007-04-30 Ulrich Drepper <drepper@redhat.com>
[BZ #4438]
* stdio-common/vfprintf.c (process_string_arg): Don't overflow the
stack for large precisions.
* stdio-common/test-vfprintf.c (main): Add test for large
precision.
git-svn-id: svn://svn.eglibc.org/branches/eglibc-2_5@4804 7b3dc134-2b1b-0410-93df-9e9f96275f8d
-rw-r--r-- | libc/ChangeLog.eglibc | 32 | ||||
-rw-r--r-- | libc/stdio-common/test-vfprintf.c | 8 | ||||
-rw-r--r-- | libc/stdio-common/tst-sprintf.c | 21 | ||||
-rw-r--r-- | libc/stdio-common/vfprintf.c | 43 |
4 files changed, 85 insertions, 19 deletions
diff --git a/libc/ChangeLog.eglibc b/libc/ChangeLog.eglibc index 207cd3d20..6e63680d2 100644 --- a/libc/ChangeLog.eglibc +++ b/libc/ChangeLog.eglibc @@ -1,3 +1,35 @@ +2008-01-07 Joseph Myers <joseph@codesourcery.com> + + Merge from FSF glibc-2_5-branch: + + 2007-05-21 Jakub Jelinek <jakub@redhat.com> + [BZ #4514] + * stdio-common/vfprintf.c (vfprintf): Don't shadow workstart variable, + reinitialize workend at the start of each do_positional format spec + loop, free workstart before do_positional loops. + (printf_unknown): Fix size of work_buffer. + * stdio-common/tst-sprintf.c (main): Add 3 new testcases. + + 2007-05-06 Ulrich Drepper <drepper@redhat.com> + * stdio-common/vfprintf.c (process_string_arg): Optimize + ridiculous precision in wide char code printing multi-byte string. + Reported by Jim Meyering <jim@meyering.net>. + + 2007-05-04 Ulrich Drepper <drepper@redhat.com> + * stdio-common/vfprintf.c (process_string_arg): Adjust call to + __mbsnrtowcs after last change. + + 2007-05-02 Jakub Jelinek <jakub@redhat.com> + * stdio-common/vfprintf.c (process_string_arg): Use a VLA rather than + fixed length array for ignore. + + 2007-04-30 Ulrich Drepper <drepper@redhat.com> + [BZ #4438] + * stdio-common/vfprintf.c (process_string_arg): Don't overflow the + stack for large precisions. + * stdio-common/test-vfprintf.c (main): Add test for large + precision. + 2007-10-28 Joseph Myers <joseph@codesourcery.com> Backport: diff --git a/libc/stdio-common/test-vfprintf.c b/libc/stdio-common/test-vfprintf.c index a683eac77..342ac471d 100644 --- a/libc/stdio-common/test-vfprintf.c +++ b/libc/stdio-common/test-vfprintf.c @@ -1,5 +1,5 @@ /* Tests of *printf for very large strings. - Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2000. @@ -94,6 +94,7 @@ main (void) fprintf (fp, "%.*s", 30000, large); large[20000] = '\0'; fprintf (fp, large); + fprintf (fp, "%-1.300000000s", "hello"); if (fflush (fp) != 0 || ferror (fp) != 0 || fclose (fp) != 0) { @@ -108,11 +109,12 @@ main (void) setlocale (LC_ALL, NULL)); exit (1); } - else if (st.st_size != 99999) + else if (st.st_size != 50000 + 30000 + 19999 + 5) { printf ("file size incorrect for locale %s: %jd instead of %jd\n", setlocale (LC_ALL, NULL), - (intmax_t) st.st_size, (intmax_t) 99999); + (intmax_t) st.st_size, + (intmax_t) 50000 + 30000 + 19999 + 5); res = 1; } else diff --git a/libc/stdio-common/tst-sprintf.c b/libc/stdio-common/tst-sprintf.c index c61d3b50e..c04fef18f 100644 --- a/libc/stdio-common/tst-sprintf.c +++ b/libc/stdio-common/tst-sprintf.c @@ -37,5 +37,26 @@ main (void) free (dst); } + if (sprintf (buf, "%1$d%3$.*2$s%4$d", 7, 67108863, "x", 8) != 3 + || strcmp (buf, "7x8") != 0) + { + printf ("sprintf (buf, \"%%1$d%%3$.*2$s%%4$d\", 7, 67108863, \"x\", 8) produced `%s' output", buf); + result = 1; + } + + if (sprintf (buf, "%67108863.16\"%d", 7) != 14 + || strcmp (buf, "%67108863.16\"7") != 0) + { + printf ("sprintf (buf, \"%%67108863.16\\\"%%d\", 7) produced `%s' output", buf); + result = 1; + } + + if (sprintf (buf, "%*\"%d", 0x3ffffff, 7) != 11 + || strcmp (buf, "%67108863\"7") != 0) + { + printf ("sprintf (buf, \"%%*\\\"%%d\", 0x3ffffff, 7) produced `%s' output", buf); + result = 1; + } + return result; } diff --git a/libc/stdio-common/vfprintf.c b/libc/stdio-common/vfprintf.c index 53339f307..bf5227873 100644 --- a/libc/stdio-common/vfprintf.c +++ b/libc/stdio-common/vfprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006 +/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -1025,10 +1025,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) const char *mbs = (const char *) string; \ mbstate_t mbstate; \ \ - len = prec != -1 ? (size_t) prec : strlen (mbs); \ + len = prec != -1 ? __strnlen (mbs, (size_t) prec) : strlen (mbs); \ \ /* Allocate dynamically an array which definitely is long \ - enough for the wide character version. */ \ + enough for the wide character version. Each byte in the \ + multi-byte string can produce at most one wide character. */ \ if (__libc_use_alloca (len * sizeof (wchar_t))) \ string = (CHAR_T *) alloca (len * sizeof (wchar_t)); \ else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t))) \ @@ -1159,19 +1160,26 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) else \ { \ /* In case we have a multibyte character set the \ - situation is more compilcated. We must not copy \ + situation is more complicated. We must not copy \ bytes at the end which form an incomplete character. */\ - wchar_t ignore[prec]; \ + size_t ignore_size = (unsigned) prec > 1024 ? 1024 : prec;\ + wchar_t ignore[ignore_size]; \ const char *str2 = string; \ - mbstate_t ps; \ + const char *strend = string + prec; \ + if (strend < string) \ + strend = (const char *) UINTPTR_MAX; \ \ + mbstate_t ps; \ memset (&ps, '\0', sizeof (ps)); \ - if (__mbsnrtowcs (ignore, &str2, prec, prec, &ps) \ - == (size_t) -1) \ - { \ - done = -1; \ - goto all_done; \ - } \ + \ + while (str2 != NULL && str2 < strend) \ + if (__mbsnrtowcs (ignore, &str2, strend - str2, \ + ignore_size, &ps) == (size_t) -1) \ + { \ + done = -1; \ + goto all_done; \ + } \ + \ if (str2 == NULL) \ len = strlen (string); \ else \ @@ -1618,6 +1626,8 @@ do_positional: /* Just a counter. */ size_t cnt; + free (workstart); + workstart = NULL; if (grouping == (const char *) -1) { @@ -1792,7 +1802,9 @@ do_positional: int use_outdigits = specs[nspecs_done].info.i18n; char pad = specs[nspecs_done].info.pad; CHAR_T spec = specs[nspecs_done].info.spec; - CHAR_T *workstart = NULL; + + workstart = NULL; + workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; /* Fill in last information. */ if (specs[nspecs_done].width_arg != -1) @@ -1888,8 +1900,7 @@ do_positional: break; } - if (__builtin_expect (workstart != NULL, 0)) - free (workstart); + free (workstart); workstart = NULL; /* Write the following constant string. */ @@ -1917,7 +1928,7 @@ printf_unknown (FILE *s, const struct printf_info *info, { int done = 0; - CHAR_T work_buffer[MAX (info->width, info->spec) + 32]; + CHAR_T work_buffer[MAX (sizeof (info->width), sizeof (info->prec)) * 3]; CHAR_T *const workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; register CHAR_T *w; |