diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | stdio-common/_i18n_number.h | 24 | ||||
-rw-r--r-- | stdio-common/printf_fp.c | 23 | ||||
-rw-r--r-- | stdio-common/vfprintf.c | 4 |
4 files changed, 47 insertions, 13 deletions
@@ -1,5 +1,14 @@ 2008-07-25 Ulrich Drepper <drepper@redhat.com> + [BZ #6698] + * stdio-common/_i18n_number.h (_i18n_number_rewrite): Take additional + parameter for end of buffer. If temporary copy is too large use + malloc. + * stdio-common/vfprintf.c: Adjust for _i18n_number_rewrite + interface change. + * stdio-common/printf_fp.c (__printf_fp): Likewise.. Account for + string rewrite when allocating buffer. + * sysdeps/unix/sysv/linux/kernel-features.h: PPC has the new syscalls, too. diff --git a/stdio-common/_i18n_number.h b/stdio-common/_i18n_number.h index 04d6619b4c..8bb56190c6 100644 --- a/stdio-common/_i18n_number.h +++ b/stdio-common/_i18n_number.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2004, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. @@ -24,7 +24,7 @@ #include "../locale/outdigitswc.h" static CHAR_T * -_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr) +_i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr, CHAR_T *end) { #ifdef COMPILE_WPRINTF # define decimal NULL @@ -58,10 +58,23 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr) #endif /* Copy existing string so that nothing gets overwritten. */ - CHAR_T *src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); + CHAR_T *src; + bool use_alloca = __libc_use_alloca ((rear_ptr - w) * sizeof (CHAR_T)); + if (__builtin_expect (use_alloca, true)) + src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); + else + { + src = (CHAR_T *) malloc ((rear_ptr - w) * sizeof (CHAR_T)); + if (src == NULL) + /* If we cannot allocate the memory don't rewrite the string. + It is better than nothing. */ + return w; + } + CHAR_T *s = (CHAR_T *) __mempcpy (src, w, (rear_ptr - w) * sizeof (CHAR_T)); - w = rear_ptr; + + w = end; /* Process all characters in the string. */ while (--s >= src) @@ -91,5 +104,8 @@ _i18n_number_rewrite (CHAR_T *w, CHAR_T *rear_ptr) } } + if (! use_alloca) + free (src); + return w; } diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index c65cfa9faa..d63be7f92d 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -1,5 +1,5 @@ /* Floating point output for `printf'. - Copyright (C) 1995-2003, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 1995-2003, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. @@ -1148,6 +1148,7 @@ ___printf_fp (FILE *fp, { char *buffer = NULL; + char *buffer_end = NULL; char *cp = NULL; char *tmpptr; @@ -1157,6 +1158,9 @@ ___printf_fp (FILE *fp, size_t decimal_len; size_t thousands_sep_len; wchar_t *copywc; + size_t factor = (info->i18n + ? _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MB_CUR_MAX) + : 1); decimal_len = strlen (decimal); @@ -1165,10 +1169,11 @@ ___printf_fp (FILE *fp, else thousands_sep_len = strlen (thousands_sep); + size_t nbuffer = (2 + chars_needed * factor + decimal_len + + ngroups * thousands_sep_len); if (__builtin_expect (buffer_malloced, 0)) { - buffer = (char *) malloc (2 + chars_needed + decimal_len - + ngroups * thousands_sep_len); + buffer = (char *) malloc (nbuffer); if (buffer == NULL) { /* Signal an error to the caller. */ @@ -1177,8 +1182,8 @@ ___printf_fp (FILE *fp, } } else - buffer = (char *) alloca (2 + chars_needed + decimal_len - + ngroups * thousands_sep_len); + buffer = (char *) alloca (nbuffer); + buffer_end = buffer + nbuffer; /* Now copy the wide character string. Since the character (except for the decimal point and thousands separator) must @@ -1197,9 +1202,13 @@ ___printf_fp (FILE *fp, if (__builtin_expect (info->i18n, 0)) { #ifdef COMPILE_WPRINTF - wstartp = _i18n_number_rewrite (wstartp, wcp); + wstartp = _i18n_number_rewrite (wstartp, wcp, + wbuffer + wbuffer_to_alloc); #else - tmpptr = _i18n_number_rewrite (tmpptr, cp); + tmpptr = _i18n_number_rewrite (tmpptr, cp, buffer_end); + cp = buffer_end; + assert ((uintptr_t) buffer <= (uintptr_t) tmpptr); + assert ((uintptr_t) tmpptr < (uintptr_t) buffer_end); #endif } diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 714c76c3d4..5d5bb5e578 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -625,7 +625,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) thousands_sep); \ \ if (use_outdigits && base == 10) \ - string = _i18n_number_rewrite (string, workend); \ + string = _i18n_number_rewrite (string, workend, workend); \ } \ /* Simplify further test for num != 0. */ \ number.word = number.longlong != 0; \ @@ -683,7 +683,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap) thousands_sep); \ \ if (use_outdigits && base == 10) \ - string = _i18n_number_rewrite (string, workend); \ + string = _i18n_number_rewrite (string, workend, workend); \ } \ } \ \ |