]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Fix small bugs in the *printf emulations.
authorBruno Haible <bruno@clisp.org>
Mon, 9 Oct 2006 12:01:40 +0000 (12:01 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:14:06 +0000 (12:14 +0200)
gettext-runtime/intl/ChangeLog
gettext-runtime/intl/printf.c

index 7fa5256a43952f4dd5d1436a0ef9728f77f5e69d..fa7239f522714bb947205cab81762e8505b38491 100644 (file)
@@ -1,3 +1,17 @@
+2006-10-08  Bruno Haible  <bruno@clisp.org>
+
+       * 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  <bruno@clisp.org>
 
        * lock.c: Include <config.h> unconditionally.
index 275968b3777eaa66ae985f9a6d5dd5881913a38f..004c66f783d1914199507d4c0ce78a879364d84d 100644 (file)
@@ -47,9 +47,16 @@ char *alloca ();
 
 #if !HAVE_POSIX_PRINTF
 
+#include <errno.h>
+#include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
+/* 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