summaryrefslogtreecommitdiffstats
path: root/gettext-runtime/libasprintf/vasnprintf.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2003-11-18 15:25:27 +0000
committerBruno Haible <bruno@clisp.org>2009-06-23 12:11:18 +0200
commit70d5749d069b7ac3a4d456254414e5c15cad117e (patch)
tree63a58b6397f64c7537f3c3700e2dedfca0d37627 /gettext-runtime/libasprintf/vasnprintf.c
parent151f856b27279d9844516450c4225c17473488d2 (diff)
downloadexternal_gettext-70d5749d069b7ac3a4d456254414e5c15cad117e.zip
external_gettext-70d5749d069b7ac3a4d456254414e5c15cad117e.tar.gz
external_gettext-70d5749d069b7ac3a4d456254414e5c15cad117e.tar.bz2
Be careful about using alloca.
Diffstat (limited to 'gettext-runtime/libasprintf/vasnprintf.c')
-rw-r--r--gettext-runtime/libasprintf/vasnprintf.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/gettext-runtime/libasprintf/vasnprintf.c b/gettext-runtime/libasprintf/vasnprintf.c
index 1415a6f..05a08bc 100644
--- a/gettext-runtime/libasprintf/vasnprintf.c
+++ b/gettext-runtime/libasprintf/vasnprintf.c
@@ -52,15 +52,6 @@
/* Checked size_t computations. */
#include "xsize.h"
-/* For those losing systems which don't have 'alloca' we have to add
- some additional code emulating it. */
-#ifdef HAVE_ALLOCA
-# define freea(p) /* nothing */
-#else
-# define alloca(n) malloc (n)
-# define freea(p) free (p)
-#endif
-
#ifdef HAVE_WCHAR_T
# ifdef HAVE_WCSLEN
# define local_wcslen wcslen
@@ -140,10 +131,9 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
}
{
- size_t buf_neededlength =
- xsum4 (7, d.max_width_length, d.max_precision_length, 6);
- CHAR_T *buf =
- (CHAR_T *) alloca (xtimes (buf_neededlength, sizeof (CHAR_T)));
+ size_t buf_neededlength;
+ CHAR_T *buf;
+ CHAR_T *buf_malloced;
const CHAR_T *cp;
size_t i;
DIRECTIVE *dp;
@@ -152,6 +142,28 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
size_t allocated;
size_t length;
+ /* Allocate a small buffer that will hold a directive passed to
+ sprintf or snprintf. */
+ buf_neededlength =
+ xsum4 (7, d.max_width_length, d.max_precision_length, 6);
+#if HAVE_ALLOCA
+ if (buf_neededlength < 4000 / sizeof (CHAR_T))
+ {
+ buf = (CHAR_T *) alloca (buf_neededlength * sizeof (CHAR_T));
+ buf_malloced = NULL;
+ }
+ else
+#endif
+ {
+ size_t buf_memsize = xtimes (buf_neededlength, sizeof (CHAR_T));
+ if (size_overflow_p (buf_memsize))
+ goto out_of_memory_1;
+ buf = (CHAR_T *) malloc (buf_memsize);
+ if (buf == NULL)
+ goto out_of_memory_1;
+ buf_malloced = buf;
+ }
+
if (resultbuf != NULL)
{
result = resultbuf;
@@ -789,7 +801,8 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
{
if (!(result == resultbuf || result == NULL))
free (result);
- freea (buf);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
CLEANUP ();
errno = EINVAL;
return NULL;
@@ -847,7 +860,8 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
result = memory;
}
- freea (buf);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
CLEANUP ();
*lengthp = length;
return result;
@@ -855,7 +869,9 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar
out_of_memory:
if (!(result == resultbuf || result == NULL))
free (result);
- freea (buf);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ out_of_memory_1:
CLEANUP ();
errno = ENOMEM;
return NULL;