diff options
Diffstat (limited to 'libgnu/vasnprintf.c')
-rw-r--r-- | libgnu/vasnprintf.c | 65 |
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 |