summaryrefslogtreecommitdiffstats
path: root/libgnu/vasnprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgnu/vasnprintf.c')
-rw-r--r--libgnu/vasnprintf.c65
1 files changed, 43 insertions, 22 deletions
diff --git a/libgnu/vasnprintf.c b/libgnu/vasnprintf.c
index d654689d..3b441d03 100644
--- a/libgnu/vasnprintf.c
+++ b/libgnu/vasnprintf.c
@@ -1,5 +1,5 @@
/* vsprintf with automatic memory allocation.
- Copyright (C) 1999, 2002-2017 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002-2018 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -12,7 +12,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
- with this program; if not, see <http://www.gnu.org/licenses/>. */
+ with this program; if not, see <https://www.gnu.org/licenses/>. */
/* This file can be parametrized with the following macros:
VASNPRINTF The name of the function being defined.
@@ -118,6 +118,14 @@
# include "fpucw.h"
#endif
+#ifndef FALLTHROUGH
+# if __GNUC__ < 7
+# define FALLTHROUGH ((void) 0)
+# else
+# define FALLTHROUGH __attribute__ ((__fallthrough__))
+# endif
+#endif
+
/* Default parameters. */
#ifndef VASNPRINTF
# if WIDE_CHAR_VERSION
@@ -156,6 +164,7 @@
# define SNPRINTF snwprintf
# else
# define SNPRINTF _snwprintf
+# define USE_MSVC__SNPRINTF 1
# endif
# else
/* Unix. */
@@ -181,7 +190,9 @@
/* Here we need to call the native snprintf, not rpl_snprintf. */
# undef snprintf
# else
+ /* MSVC versions < 14 did not have snprintf, only _snprintf. */
# define SNPRINTF _snprintf
+# define USE_MSVC__SNPRINTF 1
# endif
# else
/* Unix. */
@@ -208,7 +219,7 @@
#undef remainder
#define remainder rem
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
+#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && !WIDE_CHAR_VERSION
# if (HAVE_STRNLEN && !defined _AIX)
# define local_strnlen strnlen
# else
@@ -224,7 +235,7 @@ local_strnlen (const char *string, size_t maxlen)
# endif
#endif
-#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
+#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
# if HAVE_WCSLEN
# define local_wcslen wcslen
# else
@@ -247,7 +258,7 @@ local_wcslen (const wchar_t *s)
# endif
#endif
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
+#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
# if HAVE_WCSNLEN
# define local_wcsnlen wcsnlen
# else
@@ -1517,7 +1528,7 @@ is_borderline (const char *digits, size_t precision)
#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
/* Use a different function name, to make it possible that the 'wchar_t'
parametrization and the 'char' parametrization get compiled in the same
@@ -2392,7 +2403,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
#endif
-#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
+#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
else if (dp->conversion == 's'
# if WIDE_CHAR_VERSION
&& a.arg[dp->arg_index].type != TYPE_WIDE_STRING
@@ -4232,7 +4243,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
static const wchar_t decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
{ '%', '+', '.', '3', 'd', '\0' };
# else
{ '%', '+', '.', '2', 'd', '\0' };
@@ -4246,7 +4257,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
static const char decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
"%+.3d";
# else
"%+.2d";
@@ -4425,7 +4436,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
static const wchar_t decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
{ '%', '+', '.', '3', 'd', '\0' };
# else
{ '%', '+', '.', '2', 'd', '\0' };
@@ -4439,7 +4450,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
static const char decimal_format[] =
/* Produce the same number of exponent digits
as the native printf implementation. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
"%+.3d";
# else
"%+.2d";
@@ -4497,7 +4508,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
*p++ = '+';
/* Produce the same number of exponent digits as
the native printf implementation. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
*p++ = '0';
# endif
*p++ = '0';
@@ -4591,10 +4602,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int has_width;
#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
size_t width;
#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
int has_precision;
size_t precision;
#endif
@@ -4623,7 +4634,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 0;
#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
width = 0;
if (dp->width_start != dp->width_end)
{
@@ -4657,7 +4668,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
#endif
-#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || NEED_PRINTF_UNBOUNDED_PRECISION
has_precision = 0;
precision = 6;
if (dp->precision_start != dp->precision_end)
@@ -4825,7 +4836,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#if HAVE_LONG_LONG_INT
case TYPE_LONGLONGINT:
case TYPE_ULONGLONGINT:
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if defined _WIN32 && ! defined __CYGWIN__
*fbp++ = 'I';
*fbp++ = '6';
*fbp++ = '4';
@@ -4834,7 +4845,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
*fbp++ = 'l';
# endif
#endif
- /*FALLTHROUGH*/
+ FALLTHROUGH;
case TYPE_LONGINT:
case TYPE_ULONGINT:
#if HAVE_WINT_T
@@ -4858,7 +4869,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#endif
*fbp = dp->conversion;
#if USE_SNPRINTF
-# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+# if ! (((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \
+ && !defined __UCLIBC__) \
+ || (defined __APPLE__ && defined __MACH__) \
+ || (defined _WIN32 && ! defined __CYGWIN__))
fbp[1] = '%';
fbp[2] = 'n';
fbp[3] = '\0';
@@ -4872,6 +4886,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
in format strings in writable memory may crash the program
(if compiled with _FORTIFY_SOURCE=2), so we should avoid it
in this situation. */
+ /* On Mac OS X 10.3 or newer, we know that snprintf's return
+ value conforms to ISO C 99: the tests gl_SNPRINTF_RETVAL_C99
+ and gl_SNPRINTF_TRUNCATION_C99 pass.
+ Therefore we can avoid using %n in this situation.
+ On Mac OS X 10.13 or newer, the use of %n in format strings
+ in writable memory by default crashes the program, so we
+ should avoid it in this situation. */
/* On native Windows systems (such as mingw), we can avoid using
%n because:
- Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
@@ -4884,8 +4905,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
On native Windows systems (such as mingw) where the OS is
Windows Vista, the use of %n in format strings by default
crashes the program. See
- <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
- <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
+ <https://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
+ <https://msdn.microsoft.com/en-us/library/ms175782.aspx>
So we should avoid %n in this situation. */
fbp[1] = '\0';
# endif
@@ -5127,7 +5148,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* Look at the snprintf() return value. */
if (retcount < 0)
{
-# if !HAVE_SNPRINTF_RETVAL_C99
+# if !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF
/* HP-UX 10.20 snprintf() is doubly deficient:
It doesn't understand the '%n' directive,
*and* it returns -1 (rather than the length