From: Bruno Haible Date: Mon, 9 Oct 2006 12:01:40 +0000 (+0000) Subject: Fix small bugs in the *printf emulations. X-Git-Tag: 0.16.x-branchpoint~97 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5923cceb61ebcc303e64bee0ad7e7349423d036b;p=thirdparty%2Fgettext.git Fix small bugs in the *printf emulations. --- diff --git a/gettext-runtime/intl/ChangeLog b/gettext-runtime/intl/ChangeLog index 7fa5256a4..fa7239f52 100644 --- a/gettext-runtime/intl/ChangeLog +++ b/gettext-runtime/intl/ChangeLog @@ -1,3 +1,17 @@ +2006-10-08 Bruno Haible + + * printf.c: Include errno.h, limits.h. + (EOVERFLOW): New fallback definition. + (libintl_vfprintf): Test whether the output length is > INT_MAX. + (libintl_vsprintf): Likewise. + (libintl_vsnprintf): Fix bug when vasnprintf requested more space than + needed. Fix return value when the entire result string would be larger + than the provided buffer. Test whether the output length is > INT_MAX. + (libintl_vasprintf): Test whether the output length is > INT_MAX. + (libintl_vfwprintf): Likewise. + (libintl_vswprintf): Fix bug when vasnwprintf requested more space than + needed. Test whether the output length is > INT_MAX. + 2006-09-14 Bruno Haible * lock.c: Include unconditionally. diff --git a/gettext-runtime/intl/printf.c b/gettext-runtime/intl/printf.c index 275968b37..004c66f78 100644 --- a/gettext-runtime/intl/printf.c +++ b/gettext-runtime/intl/printf.c @@ -47,9 +47,16 @@ char *alloca (); #if !HAVE_POSIX_PRINTF +#include +#include #include #include +/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */ +#ifndef EOVERFLOW +# define EOVERFLOW E2BIG +#endif + /* When building a DLL, we must export some functions. Note that because the functions are only defined for binary backward compatibility, we don't need to use __declspec(dllimport) in any case. */ @@ -96,9 +103,15 @@ libintl_vfprintf (FILE *stream, const char *format, va_list args) int retval = -1; if (result != NULL) { - if (fwrite (result, 1, length, stream) == length) - retval = length; + size_t written = fwrite (result, 1, length, stream); free (result); + if (written == length) + { + if (length > INT_MAX) + errno = EOVERFLOW; + else + retval = length; + } } return retval; } @@ -152,6 +165,11 @@ libintl_vsprintf (char *resultbuf, const char *format, va_list args) free (result); return -1; } + if (length > INT_MAX) + { + errno = EOVERFLOW; + return -1; + } else return length; } @@ -194,12 +212,16 @@ libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list a { if (maxlength > 0) { - if (length < maxlength) - abort (); - memcpy (resultbuf, result, maxlength - 1); - resultbuf[maxlength - 1] = '\0'; + size_t pruned_length = + (length < maxlength ? length : maxlength - 1); + memcpy (resultbuf, result, pruned_length); + resultbuf[pruned_length] = '\0'; } free (result); + } + if (length > INT_MAX) + { + errno = EOVERFLOW; return -1; } else @@ -232,6 +254,12 @@ libintl_vasprintf (char **resultp, const char *format, va_list args) char *result = libintl_vasnprintf (NULL, &length, format, args); if (result == NULL) return -1; + if (length > INT_MAX) + { + free (result); + errno = EOVERFLOW; + return -1; + } *resultp = result; return length; } @@ -293,9 +321,14 @@ libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args) for (i = 0; i < length; i++) if (fputwc (result[i], stream) == WEOF) break; - if (i == length) - retval = length; free (result); + if (i == length) + { + if (length > INT_MAX) + errno = EOVERFLOW; + else + retval = length; + } } return retval; } @@ -348,12 +381,22 @@ libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_ { if (maxlength > 0) { - if (length < maxlength) - abort (); - memcpy (resultbuf, result, (maxlength - 1) * sizeof (wchar_t)); - resultbuf[maxlength - 1] = 0; + size_t pruned_length = + (length < maxlength ? length : maxlength - 1); + memcpy (resultbuf, result, pruned_length * sizeof (wchar_t)); + resultbuf[pruned_length] = 0; } free (result); + /* Unlike vsnprintf, which has to return the number of character that + would have been produced if the resultbuf had been sufficiently + large, the vswprintf function has to return a negative value if + the resultbuf was not sufficiently large. */ + if (length >= maxlength) + return -1; + } + if (length > INT_MAX) + { + errno = EOVERFLOW; return -1; } else