diff options
author | Bruno Haible <bruno@clisp.org> | 2003-11-18 15:25:27 +0000 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2009-06-23 12:11:18 +0200 |
commit | 70d5749d069b7ac3a4d456254414e5c15cad117e (patch) | |
tree | 63a58b6397f64c7537f3c3700e2dedfca0d37627 /gettext-runtime/libasprintf/vasnprintf.c | |
parent | 151f856b27279d9844516450c4225c17473488d2 (diff) | |
download | external_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.c | 48 |
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; |