summaryrefslogtreecommitdiffstats
path: root/intl/printf.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/printf.c')
-rw-r--r--intl/printf.c77
1 files changed, 64 insertions, 13 deletions
diff --git a/intl/printf.c b/intl/printf.c
index 5e112b6..004c66f 100644
--- a/intl/printf.c
+++ b/intl/printf.c
@@ -1,5 +1,5 @@
/* Formatted output to strings, using POSIX/XSI format strings with positions.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software; you can redistribute it and/or modify it
@@ -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. */
@@ -61,6 +68,14 @@ char *alloca ();
#define STATIC static
+/* This needs to be consistent with libgnuintl.h.in. */
+#if defined __NetBSD__ || defined __CYGWIN__ || defined __MINGW32__
+/* Don't break __attribute__((format(printf,M,N))).
+ This redefinition is only possible because the libc in NetBSD, Cygwin,
+ mingw does not have a function __printf__. */
+# define libintl_printf __printf__
+#endif
+
/* Define auxiliary functions declared in "printf-args.h". */
#include "printf-args.c"
@@ -88,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;
}
@@ -144,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;
}
@@ -186,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
@@ -224,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;
}
@@ -285,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;
}
@@ -340,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