[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
another vasnprintf fix
From: |
Bruno Haible |
Subject: |
another vasnprintf fix |
Date: |
Tue, 20 Mar 2007 01:46:04 +0100 |
User-agent: |
KMail/1.5.4 |
Performing the unit tests on NetBSD 3.0 uncovered this: When the "size of
given buffer" argument passed to vasnprintf() was > INT_MAX, the function
could loop endlessly instead of failing with EOVERFLOW.
Note: NetBSD also has a bug here: snprintf() returns -1 with errno = EINVAL,
where POSIX says that it should return -1 with errno = EOVERFLOW.
2007-03-17 Bruno Haible <address@hidden>
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.
*** lib/vasnprintf.c 17 Mar 2007 20:07:01 -0000 1.29
--- lib/vasnprintf.c 18 Mar 2007 00:26:47 -0000
***************
*** 59,64 ****
--- 62,72 ----
# 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,184 ****
--- 187,196 ----
{
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,1112 ****
--- 1133,1141 ----
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,1387 ****
--- 1411,1425 ----
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);
*** lib/vsprintf.c 8 Mar 2007 03:24:38 -0000 1.2
--- lib/vsprintf.c 18 Mar 2007 00:26:47 -0000
***************
*** 46,52 ****
{
char *output;
size_t len;
! size_t lenbuf = SIZE_MAX;
output = vasnprintf (str, &lenbuf, format, args);
len = lenbuf;
--- 46,54 ----
{
char *output;
size_t len;
! /* 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;
*** lib/sprintf.c 8 Mar 2007 03:24:38 -0000 1.2
--- lib/sprintf.c 18 Mar 2007 00:26:47 -0000
***************
*** 46,52 ****
{
char *output;
size_t len;
! size_t lenbuf = SIZE_MAX;
va_list args;
va_start (args, format);
--- 46,54 ----
{
char *output;
size_t len;
! /* 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);