C95 compatible (v)swprintf function takes size argument and returns negative value on error. __mingw_(v)swprintf function (which is called when __USE_MINGW_ANSI_STDIO=1) does not take size argument at all.
Fix this problem by adjusting mingw_sprintfw.c and mingw_vsprintfw.c files to include "n" function variant and also adjust mingw_vsnprintf.c implementation to return correct value on error for ISO C95+ variant. Fix also header files to provide correct declarations for __mingw_(v)swprintf() function and then also inline definitions for (v)swprintf() when __USE_MINGW_ANSI_STDIO=1. Note that mingw-w64 provides also additional non-ISO C (v)snwprintf() function which is built from the same mingw_vsnprintf.c source file. Distinguish between non-ISO C (v)snwprintf() and ISO C95+ (v)swprintf() by a new __BUILD_WIDEAPI_ISO macro. With all these changes, functions swprintf() and vswprintf() when __USE_MINGW_ANSI_STDIO is set to 1 are now compatible with ISO C95+. --- mingw-w64-crt/stdio/mingw_pformat.h | 11 +++++++-- mingw-w64-crt/stdio/mingw_sprintfw.c | 4 +-- mingw-w64-crt/stdio/mingw_vsnprintf.c | 18 ++++++++++++++ mingw-w64-crt/stdio/mingw_vsprintfw.c | 4 +-- mingw-w64-headers/crt/stdio.h | 35 ++++++++++++++++++++++++--- mingw-w64-headers/crt/wchar.h | 23 +++++++++++++----- 6 files changed, 79 insertions(+), 16 deletions(-) diff --git a/mingw-w64-crt/stdio/mingw_pformat.h b/mingw-w64-crt/stdio/mingw_pformat.h index 4777804322ab..3381ff8ba908 100644 --- a/mingw-w64-crt/stdio/mingw_pformat.h +++ b/mingw-w64-crt/stdio/mingw_pformat.h @@ -72,13 +72,20 @@ # define __printf __mingw_wprintf # define __fprintf __mingw_fwprintf -# define __sprintf __mingw_swprintf +#ifdef __BUILD_WIDEAPI_ISO +# define __snprintf __mingw_swprintf +#else # define __snprintf __mingw_snwprintf +#endif # define __vprintf __mingw_vwprintf # define __vfprintf __mingw_vfwprintf -# define __vsprintf __mingw_vswprintf +#ifdef __BUILD_WIDEAPI_ISO +# define __vsnprintf __mingw_vswprintf +#else # define __vsnprintf __mingw_vsnwprintf +#endif + #else # define __pformat __mingw_pformat #define __fputc(X,STR) fputc((X), (STR)) diff --git a/mingw-w64-crt/stdio/mingw_sprintfw.c b/mingw-w64-crt/stdio/mingw_sprintfw.c index 0baf1e4f387d..179c27970e6b 100644 --- a/mingw-w64-crt/stdio/mingw_sprintfw.c +++ b/mingw-w64-crt/stdio/mingw_sprintfw.c @@ -4,7 +4,7 @@ * No warranty is given; refer to the file DISCLAIMER.PD within this package. */ #define __BUILD_WIDEAPI 1 -#define _CRT_NON_CONFORMING_SWPRINTFS 1 +#define __BUILD_WIDEAPI_ISO 1 -#include "mingw_sprintf.c" +#include "mingw_snprintf.c" diff --git a/mingw-w64-crt/stdio/mingw_vsnprintf.c b/mingw-w64-crt/stdio/mingw_vsnprintf.c index b477300f9700..b9c3578627d1 100644 --- a/mingw-w64-crt/stdio/mingw_vsnprintf.c +++ b/mingw-w64-crt/stdio/mingw_vsnprintf.c @@ -34,11 +34,20 @@ int __cdecl __vsnprintf(APICHAR *buf, size_t length, const APICHAR *fmt, va_list register int retval; if( length == (size_t)(0) ) + { +#if defined(__BUILD_WIDEAPI) && defined(__BUILD_WIDEAPI_ISO) + /* No buffer; for wide api ISO C95+ vswprintf() function + * simply returns negative value as required by ISO C95+. + */ + return -1; +#else /* * No buffer; simply compute and return the size required, * without actually emitting any data. */ return __pformat( 0, buf, 0, fmt, argv); +#endif + } /* If we get to here, then we have a buffer... * Emit data up to the limit of buffer length less one, @@ -47,6 +56,15 @@ int __cdecl __vsnprintf(APICHAR *buf, size_t length, const APICHAR *fmt, va_list retval = __pformat( 0, buf, --length, fmt, argv ); buf[retval < (int) length ? retval : (int)length] = '\0'; +#if defined(__BUILD_WIDEAPI) && defined(__BUILD_WIDEAPI_ISO) + /* For wide api ISO C95+ vswprintf() when requested length + * is equal or larger than buffer length, returns negative + * value as required by ISO C95+. + */ + if( retval >= (int) length ) + retval = -1; +#endif + return retval; } diff --git a/mingw-w64-crt/stdio/mingw_vsprintfw.c b/mingw-w64-crt/stdio/mingw_vsprintfw.c index fd8808bf477d..6d70b2cfa1e5 100644 --- a/mingw-w64-crt/stdio/mingw_vsprintfw.c +++ b/mingw-w64-crt/stdio/mingw_vsprintfw.c @@ -4,7 +4,7 @@ * No warranty is given; refer to the file DISCLAIMER.PD within this package. */ #define __BUILD_WIDEAPI 1 -#define _CRT_NON_CONFORMING_SWPRINTFS 1 +#define __BUILD_WIDEAPI_ISO 1 -#include "mingw_vsprintf.c" +#include "mingw_vsnprintf.c" diff --git a/mingw-w64-headers/crt/stdio.h b/mingw-w64-headers/crt/stdio.h index 20cab73dcc00..3934754b01f1 100644 --- a/mingw-w64-headers/crt/stdio.h +++ b/mingw-w64-headers/crt/stdio.h @@ -915,10 +915,10 @@ int vsprintf (char * __restrict__ __stream, const char * __restrict__ __format, int __cdecl __mingw_snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...); /* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) int __cdecl __mingw_vsnwprintf (wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ , va_list); -/* __attribute__((__format__ (gnu_wprintf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2) - int __cdecl __mingw_swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -/* __attribute__((__format__ (gnu_wprintf, 2, 0))) */ __MINGW_ATTRIB_NONNULL(2) - int __cdecl __mingw_vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ ,va_list); +/* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) + int __cdecl __mingw_swprintf(wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ , ...); +/* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) + int __cdecl __mingw_vswprintf(wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ ,va_list); /* __attribute__((__format__ (ms_wscanf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2) int __cdecl __ms_swscanf(const wchar_t * __restrict__ _Src,const wchar_t * __restrict__ _Format,...); @@ -996,6 +996,32 @@ __MINGW_ASM_CALL(__mingw_vfwprintf); int vwprintf (const wchar_t *__format, __builtin_va_list __local_argv) __MINGW_ASM_CALL(__mingw_vwprintf); +/* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) +int swprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, ...) +__MINGW_ASM_CALL(__mingw_swprintf); + +#if __MINGW_FORTIFY_VA_ARG + +__mingw_bos_extern_ovr +/* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) +int swprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, ...) +{ + __mingw_bos_ptr_chk_warn(__stream, __n * sizeof(wchar_t), 1); + return __mingw_swprintf( __stream, __n, __format, __builtin_va_arg_pack() ); +} + +#endif /* __MINGW_FORTIFY_VA_ARG */ + +__mingw_bos_ovr +/* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) +int vswprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builtin_va_list __local_argv) +{ +#if __MINGW_FORTIFY_LEVEL > 0 + __mingw_bos_ptr_chk_warn(__stream, __n * sizeof(wchar_t), 1); +#endif + return __mingw_vswprintf( __stream, __n, __format, __local_argv ); +} + #ifndef __NO_ISOCEXT /* externs in libmingwex.a */ /* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) @@ -1023,6 +1049,7 @@ int vsnwprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builti #endif return __mingw_vsnwprintf( __stream, __n, __format, __local_argv ); } + #endif /* __NO_ISOCEXT */ #else /* !__USE_MINGW_ANSI_STDIO */ diff --git a/mingw-w64-headers/crt/wchar.h b/mingw-w64-headers/crt/wchar.h index ffa2ba25d973..25f222e85dcd 100644 --- a/mingw-w64-headers/crt/wchar.h +++ b/mingw-w64-headers/crt/wchar.h @@ -445,10 +445,10 @@ _CRTIMP FILE *__cdecl __acrt_iob_func(unsigned index); int __cdecl __mingw_snwprintf (wchar_t * __restrict__ s, size_t n, const wchar_t * __restrict__ format, ...); /* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) int __cdecl __mingw_vsnwprintf (wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ , va_list); -/* __attribute__((__format__ (gnu_wprintf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2) - int __cdecl __mingw_swprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ , ...); -/* __attribute__((__format__ (gnu_wprintf, 2, 0))) */ __MINGW_ATTRIB_NONNULL(2) - int __cdecl __mingw_vswprintf(wchar_t * __restrict__ , const wchar_t * __restrict__ ,va_list); +/* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) + int __cdecl __mingw_swprintf(wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ , ...); +/* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) + int __cdecl __mingw_vswprintf(wchar_t * __restrict__ , size_t, const wchar_t * __restrict__ ,va_list); /* __attribute__((__format__ (ms_wscanf, 2, 3))) */ __MINGW_ATTRIB_NONNULL(2) int __cdecl __ms_swscanf(const wchar_t * __restrict__ _Src,const wchar_t * __restrict__ _Format,...); @@ -526,7 +526,16 @@ __MINGW_ASM_CALL(__mingw_vfwprintf); int vwprintf (const wchar_t *__format, __builtin_va_list __local_argv) __MINGW_ASM_CALL(__mingw_vwprintf); -/*#ifndef __NO_ISOCEXT */ /* externs in libmingwex.a */ +/* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) +int swprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, ...) +__MINGW_ASM_CALL(__mingw_vswprintf); + +/* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) +int vswprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builtin_va_list __local_argv) +__MINGW_ASM_CALL(__mingw_vswprintf); + +#ifndef __NO_ISOCEXT /* externs in libmingwex.a */ + /* __attribute__((__format__ (gnu_wprintf, 3, 4))) */ __MINGW_ATTRIB_NONNULL(3) int snwprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, ...) __MINGW_ASM_CALL(__mingw_snwprintf); @@ -534,7 +543,9 @@ __MINGW_ASM_CALL(__mingw_snwprintf); /* __attribute__((__format__ (gnu_wprintf, 3, 0))) */ __MINGW_ATTRIB_NONNULL(3) int vsnwprintf (wchar_t *__stream, size_t __n, const wchar_t *__format, __builtin_va_list __local_argv) __MINGW_ASM_CALL(__mingw_vsnwprintf); -/* #endif */ /* __NO_ISOCEXT */ + +#endif /* __NO_ISOCEXT */ + #else /* !__USE_MINGW_ANSI_STDIO */ #ifdef _UCRT -- 2.20.1 _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public