ISO C does not define (v)snwprintf() function. But ISO C11 in optional Appendix K defines (v)snwprintf_s() function which has same behavior as non-wide ISO C11 Appendix K (v)snprintf_s() function (which is secure variant of (v)snprintf()).
Function (v)snwprintf() is not provided by any MS CRT library and neither by any MS header file. mingw32 runtime and mingw-w64 runtime since beginning provide function named (v)snwprintf (without leading underscore) and define it under symbol name __mingw_(v)snwprintf. This function differs from ISO C (v)swprintf() just in return value. ISO C (v)swprintf() when buffer is too small returns negative value but this (v)snwprintf() returns size of buffer in wide characters, similarly to non-wide ISO C (v)snprintf() function, and also similarly to ISO C11 Annex K (v)snwprintf_s(). This non-ISO (v)snwprintf() and both ISO C (v)snwprintf_s() and (v)snprintf() always fill trailing nul character. But when __USE_MINGW_ANSI_STDIO=0 the (v)snwprintf() is redirected to __ms_(v)snwprintf() function, which is just wrapper around msvcrt _vsnwprintf() function. And msvcrt _vsnwprintf() function does not fill trailing nul character and does not return required buffer size when output buffer is too small. So fix __ms_(v)snwprintf() functions to properly fill trailing nul character and return required size of bufer, like ISO C vsnprintf(). Also adjust header files and remove wrong symbol aliases for (v)snwprintf symbols from def files. This will make API of (v)snwprintf() function compatible for both __USE_MINGW_ANSI_STDIO=0 and __USE_MINGW_ANSI_STDIO=1 modes and also to mimics API of ISO C (v)snwprintf_s() function. --- mingw-w64-crt/Makefile.am | 2 ++ mingw-w64-crt/lib-common/msvcrt.def.in | 5 ----- mingw-w64-crt/lib32/msvcr120.def.in | 2 -- mingw-w64-crt/lib32/msvcr120d.def.in | 2 -- mingw-w64-crt/lib64/msvcr120.def.in | 2 -- mingw-w64-crt/lib64/msvcr120d.def.in | 2 -- mingw-w64-crt/stdio/snwprintf.c | 2 +- mingw-w64-crt/stdio/snwprintf_alias.c | 26 ++++++++++++++++++++++++++ mingw-w64-crt/stdio/vsnwprintf.c | 20 +++++++++++++++++++- mingw-w64-crt/stdio/vsnwprintf_alias.c | 20 ++++++++++++++++++++ mingw-w64-headers/crt/stdio.h | 22 ++++------------------ mingw-w64-headers/crt/wchar.h | 21 ++++----------------- 12 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 mingw-w64-crt/stdio/snwprintf_alias.c create mode 100644 mingw-w64-crt/stdio/vsnwprintf_alias.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 4959e04c7d9d..253554d60fef 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -172,9 +172,11 @@ src_msvcrt_common=\ stdio/acrt_iob_func.c \ stdio/strtof.c \ stdio/snprintf_alias.c \ + stdio/snwprintf_alias.c \ stdio/swprintf.c \ stdio/swprintf_alias.c \ stdio/vsnprintf_alias.c \ + stdio/vsnwprintf_alias.c \ stdio/vswprintf.c \ stdio/vswprintf_alias.c \ math/cbrt.c math/cbrtf.c \ diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in b/mingw-w64-crt/lib-common/msvcrt.def.in index 06174d347caf..6c2a4bc11482 100644 --- a/mingw-w64-crt/lib-common/msvcrt.def.in +++ b/mingw-w64-crt/lib-common/msvcrt.def.in @@ -1926,8 +1926,3 @@ F_I386(_libm_sse2_tan_precise) #define USE_WCSTOK_S_FOR_WCSTOK #endif #include "crt-aliases.def.in" - -; This is list of additional symbol aliases not available in any CRT library -; FIXME: check if these really are needed -snwprintf == _snwprintf -vsnwprintf == _vsnwprintf diff --git a/mingw-w64-crt/lib32/msvcr120.def.in b/mingw-w64-crt/lib32/msvcr120.def.in index cc5119877fa0..a73738e2a179 100644 --- a/mingw-w64-crt/lib32/msvcr120.def.in +++ b/mingw-w64-crt/lib32/msvcr120.def.in @@ -2235,8 +2235,6 @@ vfwscanf vfwscanf_s vprintf vprintf_s -snwprintf == _snwprintf -vsnwprintf == _vsnwprintf vscanf vscanf_s vsprintf diff --git a/mingw-w64-crt/lib32/msvcr120d.def.in b/mingw-w64-crt/lib32/msvcr120d.def.in index 8c1bfadc5b48..61b6f2472df0 100644 --- a/mingw-w64-crt/lib32/msvcr120d.def.in +++ b/mingw-w64-crt/lib32/msvcr120d.def.in @@ -2302,8 +2302,6 @@ vfwscanf vfwscanf_s vprintf vprintf_s -snwprintf == _snwprintf -vsnwprintf == _vsnwprintf vscanf vscanf_s vsprintf diff --git a/mingw-w64-crt/lib64/msvcr120.def.in b/mingw-w64-crt/lib64/msvcr120.def.in index 5060413ab5a3..f30ea31dabee 100644 --- a/mingw-w64-crt/lib64/msvcr120.def.in +++ b/mingw-w64-crt/lib64/msvcr120.def.in @@ -1592,8 +1592,6 @@ _vsnprintf_c_l _vsnprintf_l _vsnprintf_s _vsnprintf_s_l -snwprintf == _snwprintf -vsnwprintf == _vsnwprintf _vsnwprintf _vsnwprintf_l _vsnwprintf_s diff --git a/mingw-w64-crt/lib64/msvcr120d.def.in b/mingw-w64-crt/lib64/msvcr120d.def.in index 6324dd867337..9643625628a5 100644 --- a/mingw-w64-crt/lib64/msvcr120d.def.in +++ b/mingw-w64-crt/lib64/msvcr120d.def.in @@ -1651,8 +1651,6 @@ _vsnprintf_c_l _vsnprintf_l _vsnprintf_s _vsnprintf_s_l -snwprintf == _snwprintf -vsnwprintf == _vsnwprintf _vsnwprintf _vsnwprintf_l _vsnwprintf_s diff --git a/mingw-w64-crt/stdio/snwprintf.c b/mingw-w64-crt/stdio/snwprintf.c index c57a46d893ce..6abf77a44424 100644 --- a/mingw-w64-crt/stdio/snwprintf.c +++ b/mingw-w64-crt/stdio/snwprintf.c @@ -12,7 +12,7 @@ int __cdecl __ms_snwprintf(wchar_t *buffer, size_t n, const wchar_t *format, ... va_list argptr; va_start(argptr, format); - retval = _vsnwprintf(buffer, n, format, argptr); + retval = __ms_vsnwprintf(buffer, n, format, argptr); va_end(argptr); return retval; } diff --git a/mingw-w64-crt/stdio/snwprintf_alias.c b/mingw-w64-crt/stdio/snwprintf_alias.c new file mode 100644 index 000000000000..4027699d352d --- /dev/null +++ b/mingw-w64-crt/stdio/snwprintf_alias.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <stdarg.h> +#include <stddef.h> + +/* Intentionally not including stdio.h, as it unconditionally defines the + * swprintf inline, and it can't be renamed with "#define snwprintf othername" + * either, as stdio.h contains "#undef snwprintf". */ + +int __cdecl __ms_vsnwprintf(wchar_t *buffer, size_t n, const wchar_t *format, va_list arg); + +int __cdecl snwprintf(wchar_t *buffer, size_t n, const wchar_t *format, ...); +int __cdecl snwprintf(wchar_t *buffer, size_t n, const wchar_t *format, ...) +{ + int retval; + va_list argptr; + + va_start(argptr, format); + retval = __ms_vsnwprintf(buffer, n, format, argptr); + va_end(argptr); + return retval; +} diff --git a/mingw-w64-crt/stdio/vsnwprintf.c b/mingw-w64-crt/stdio/vsnwprintf.c index b5c5ae65cf74..626889a30499 100644 --- a/mingw-w64-crt/stdio/vsnwprintf.c +++ b/mingw-w64-crt/stdio/vsnwprintf.c @@ -12,5 +12,23 @@ int __cdecl __ms_vsnwprintf(wchar_t *buffer, size_t n, const wchar_t * format, int __cdecl __ms_vsnwprintf(wchar_t *buffer, size_t n, const wchar_t * format, va_list argptr) { - return _vsnwprintf(buffer, n, format, argptr); + int retval; + + /* _vsnwprintf() does not work with zero length buffer + * so count number of characters by _vscwprintf() call */ + if (n == 0) + return _vscwprintf(format, argptr); + + retval = _vsnwprintf(buffer, n, format, argptr); + + /* _vsnwprintf() does not fill trailing null character if there is not place for it */ + if (retval < 0 || (size_t)retval == n) + buffer[n-1] = '\0'; + + /* _vsnwprintf() returns negative number if buffer is too small + * so count number of characters by _vscwprintf() call */ + if (retval < 0) + retval = _vscwprintf(format, argptr); + + return retval; } diff --git a/mingw-w64-crt/stdio/vsnwprintf_alias.c b/mingw-w64-crt/stdio/vsnwprintf_alias.c new file mode 100644 index 000000000000..00db0dc9e54a --- /dev/null +++ b/mingw-w64-crt/stdio/vsnwprintf_alias.c @@ -0,0 +1,20 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <stdarg.h> +#include <stddef.h> + +/* Intentionally not including stdio.h, as it unconditionally defines the + * vswprintf inline, and it can't be renamed with "#define vsnwprintf othername" + * either, as stdio.h contains "#undef vsnwprintf". */ + +int __cdecl __ms_vsnwprintf(wchar_t *buffer, size_t n, const wchar_t *format, va_list argptr); + +int __cdecl vsnwprintf(wchar_t *buffer, size_t n, const wchar_t *format, va_list argptr); +int __cdecl vsnwprintf(wchar_t *buffer, size_t n, const wchar_t *format, va_list argptr) +{ + return __ms_vsnwprintf(buffer, n, format, argptr); +} diff --git a/mingw-w64-headers/crt/stdio.h b/mingw-w64-headers/crt/stdio.h index cd4461cec22c..d6227f689868 100644 --- a/mingw-w64-headers/crt/stdio.h +++ b/mingw-w64-headers/crt/stdio.h @@ -1235,7 +1235,7 @@ int vsnwprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builti } __mingw_ovr - int snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...) + int __cdecl snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...) { __builtin_va_list __ap; int __ret; @@ -1247,8 +1247,7 @@ int vsnwprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builti __mingw_ovr int __cdecl vsnwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, va_list arg) { - int __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, s, n, format, NULL, arg); - return __ret < 0 ? -1 : __ret; + return __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, s, n, format, NULL, arg); } #endif @@ -1287,21 +1286,8 @@ int vsnwprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builti #if __USE_MINGW_ANSI_STDIO == 0 int __cdecl __ms_snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...); int __cdecl __ms_vsnwprintf (wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ , va_list); - __mingw_ovr - int snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...) - { - int r; - va_list argp; - __builtin_va_start (argp, format); - r = _vsnwprintf (s, n, format, argp); - __builtin_va_end (argp); - return r; - } - __mingw_ovr - int __cdecl vsnwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, va_list arg) - { - return _vsnwprintf(s,n,format,arg); - } + int __cdecl snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...) __MINGW_ASM_CALL(__ms_snwprintf); + int __cdecl vsnwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, va_list arg) __MINGW_ASM_CALL(__ms_vsnwprintf); #endif #endif /* ! __NO_ISOCEXT */ diff --git a/mingw-w64-headers/crt/wchar.h b/mingw-w64-headers/crt/wchar.h index dc0fbfd85000..29323a6d95c6 100644 --- a/mingw-w64-headers/crt/wchar.h +++ b/mingw-w64-headers/crt/wchar.h @@ -759,12 +759,12 @@ __MINGW_ASM_CALL(__mingw_vsnwprintf); __builtin_va_start(__ap, format); __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, s, n, format, NULL, __ap); __builtin_va_end(__ap); - return __ret; + return __ret < 0 ? -1 : __ret; } __mingw_ovr int __cdecl vsnwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, va_list arg) { - int __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, s, n, format, NULL, arg); + int __ret = __stdio_common_vswprintf(_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, s, n, format, NULL, arg); return __ret < 0 ? -1 : __ret; } #endif @@ -786,21 +786,8 @@ __MINGW_ASM_CALL(__mingw_vsnwprintf); # undef vsnwprintf int __cdecl __ms_snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...); int __cdecl __ms_vsnwprintf (wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ , va_list); - __mingw_ovr - int snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...) - { - int r; - va_list argp; - __builtin_va_start (argp, format); - r = _vsnwprintf (s, n, format, argp); - __builtin_va_end (argp); - return r; - } - __mingw_ovr - int __cdecl vsnwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, va_list arg) - { - return _vsnwprintf(s,n,format,arg); - } + int __cdecl snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...) __MINGW_ASM_CALL(__ms_snwprintf); + int __cdecl vsnwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, va_list arg) __MINGW_ASM_CALL(__ms_vsnwprintf); #pragma pop_macro ("vsnwprintf") #pragma pop_macro ("snwprintf") #endif -- 2.20.1 _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public