From: Bruno Haible Date: Tue, 18 Nov 2003 15:29:47 +0000 (+0000) Subject: Avoid alloca with too large size. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd49eb7d1f07c6e63ee83c0af94713b1fb3e12c2;p=pspp Avoid alloca with too large size. --- diff --git a/lib/ChangeLog b/lib/ChangeLog index 10019b5e0f..6607248000 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,10 @@ +2003-11-17 Bruno Haible + + * vasnprintf.c (alloca): Remove fallback definition. + (freea): Remove definition. + (VASNPRINTF): Use alloca only for small sizes, say <= 4000 bytes. + Reported by Paul Eggert. + 2003-11-17 Jim Meyering On systems without utime and without a utimes function capable of diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 380170deef..e40994d0c8 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -51,15 +51,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 @@ -139,10 +130,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; @@ -151,6 +141,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; @@ -788,7 +800,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; @@ -846,7 +859,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; @@ -854,7 +868,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;