aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--stdio-common/_i18n_number.h24
-rw-r--r--stdio-common/printf_fp.c23
-rw-r--r--stdio-common/vfprintf.c4
4 files changed, 47 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 74e7d41b38..ee26594c72 100644
--- 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.
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); \
} \
} \
\