[BZ #6698]
authorUlrich Drepper <drepper@redhat.com>
Fri, 25 Jul 2008 23:39:16 +0000 (23:39 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 25 Jul 2008 23:39:16 +0000 (23:39 +0000)
* 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.

ChangeLog
stdio-common/_i18n_number.h
stdio-common/printf_fp.c
stdio-common/vfprintf.c

index 74e7d41..ee26594 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
 
index 04d6619..8bb5619 100644 (file)
@@ -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;
 }
index c65cfa9..d63be7f 100644 (file)
@@ -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
         }
 
index 714c76c..5d5bb5e 100644 (file)
@@ -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);     \
            }                                                                 \
        }                                                                     \
                                                                              \