From c114350b101f758aadbd236ae9ea4cb596b622fb Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 18 Mar 2007 00:31:50 +0000 Subject: [PATCH] Fix endless loop when the given allocated size was > INT_MAX. --- ChangeLog | 9 +++++++++ lib/sprintf.c | 4 +++- lib/vasnprintf.c | 21 +++++++++++++++++++++ lib/vsprintf.c | 4 +++- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42690fc14..4e472c2be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2007-03-17 Bruno Haible + Fix endless loop when the given allocated size was > INT_MAX. + * lib/vasnprintf.c (EOVERFLOW): New fallback definition. + (VASNPRINTF): Fail with EOVERFLOW when the given allocated size is + larger than INT_MAX, or when it grow to a value larger than INT_MAX. + * lib/vsprintf.c (vsprintf): Don't pass a size > INT_MAX to vasnprintf. + * lib/sprintf.c (sprintf): Likewise. + +2007-03-17 Bruno Haible + * tests/test-argp-2.sh (func_compare): Output a context diff. 2007-03-17 Bruno Haible diff --git a/lib/sprintf.c b/lib/sprintf.c index ee716895d..ab14107da 100644 --- a/lib/sprintf.c +++ b/lib/sprintf.c @@ -46,7 +46,9 @@ sprintf (char *str, const char *format, ...) { char *output; size_t len; - size_t lenbuf = SIZE_MAX; + /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger + than INT_MAX (if that fits into a 'size_t' at all). */ + size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX); va_list args; va_start (args, format); diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index b13dbd5ee..8d0f51676 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -59,6 +59,11 @@ # endif #endif +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + #if HAVE_WCHAR_T # if HAVE_WCSLEN # define local_wcslen wcslen @@ -179,6 +184,10 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar { result = resultbuf; allocated = *lengthp; + /* POSIX says that snprintf() fails with EOVERFLOW when the specified + buffer size is larger than INT_MAX. Let's do the same here. */ + if (allocated > INT_MAX) + goto overflow; } else { @@ -1107,6 +1116,9 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar retcount = 0; #if USE_SNPRINTF + /* SNPRINTF can fail if maxlen > INT_MAX. */ + if (maxlen > INT_MAX) + goto overflow; # define SNPRINTF_BUF(arg) \ switch (prefix_count) \ { \ @@ -1382,6 +1394,15 @@ VASNPRINTF (CHAR_T *resultbuf, size_t *lengthp, const CHAR_T *format, va_list ar not have this limitation. */ return result; + overflow: + if (!(result == resultbuf || result == NULL)) + free (result); + if (buf_malloced != NULL) + free (buf_malloced); + CLEANUP (); + errno = EOVERFLOW; + return NULL; + out_of_memory: if (!(result == resultbuf || result == NULL)) free (result); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d25c4a65f..a9d840d9c 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -46,7 +46,9 @@ vsprintf (char *str, const char *format, va_list args) { char *output; size_t len; - size_t lenbuf = SIZE_MAX; + /* vasnprintf fails with EOVERFLOW when the buffer size argument is larger + than INT_MAX (if that fits into a 'size_t' at all). */ + size_t lenbuf = (SIZE_MAX < INT_MAX ? SIZE_MAX : INT_MAX); output = vasnprintf (str, &lenbuf, format, args); len = lenbuf; -- 2.11.0