@@ -78,6 +78,8 @@ const char *context = "";
7878 } \
7979 } while (0)
8080
81+ #define TEST_WSTR (x , expect ) TEST_XSTR(wcscmp, wchar_t, x, expect, "%ls")
82+
8183#define TEST_FLT (x , expect ) do { \
8284 tests++; \
8385 if ((x) != (expect)) { \
@@ -212,6 +214,68 @@ int vsscanf_wrap(const char *str, const char *fmt, ...) {
212214 return ret ;
213215}
214216
217+ int vswprintf_wrap (wchar_t * buf , size_t n , const wchar_t * fmt , ...) {
218+ va_list ap ;
219+ va_start (ap , fmt );
220+ int ret = vswprintf (buf , n , fmt , ap );
221+ va_end (ap );
222+ return ret ;
223+ }
224+
225+ #ifdef _WIN32
226+ #ifdef __cplusplus
227+ int vswprintf_overload_wrap (wchar_t * buf , const wchar_t * fmt , ...) {
228+ va_list ap ;
229+ va_start (ap , fmt );
230+ int ret = vswprintf (buf , fmt , ap );
231+ va_end (ap );
232+ return ret ;
233+ }
234+ #endif
235+
236+ int _vscprintf_wrap (const char * fmt , ...) {
237+ va_list ap ;
238+ va_start (ap , fmt );
239+ int ret = _vscprintf (fmt , ap );
240+ va_end (ap );
241+ return ret ;
242+ }
243+
244+ int _vswprintf_wrap (wchar_t * buf , const wchar_t * fmt , ...) {
245+ va_list ap ;
246+ va_start (ap , fmt );
247+ int ret = _vswprintf (buf , fmt , ap );
248+ va_end (ap );
249+ return ret ;
250+ }
251+
252+ int _vsnwprintf_wrap (wchar_t * buf , size_t n , const wchar_t * fmt , ...) {
253+ va_list ap ;
254+ va_start (ap , fmt );
255+ int ret = _vsnwprintf (buf , n , fmt , ap );
256+ va_end (ap );
257+ return ret ;
258+ }
259+
260+ #ifdef __MINGW32__
261+ int vsnwprintf_wrap (wchar_t * buf , size_t n , const wchar_t * fmt , ...) {
262+ va_list ap ;
263+ va_start (ap , fmt );
264+ int ret = vsnwprintf (buf , n , fmt , ap );
265+ va_end (ap );
266+ return ret ;
267+ }
268+ #endif
269+
270+ int _vscwprintf_wrap (const wchar_t * fmt , ...) {
271+ va_list ap ;
272+ va_start (ap , fmt );
273+ int ret = _vscwprintf (fmt , ap );
274+ va_end (ap );
275+ return ret ;
276+ }
277+ #endif
278+
215279double int_to_double (uint64_t i ) {
216280 union {
217281 uint64_t i ;
@@ -221,6 +285,12 @@ double int_to_double(uint64_t i) {
221285 return u .d ;
222286}
223287
288+ void fill_wchar (wchar_t * buf , wchar_t c , size_t n ) {
289+ for (size_t i = 0 ; i < n ; i ++ )
290+ buf [i ] = c ;
291+ }
292+
293+ #define ARRAYLEN (x ) (sizeof(x)/sizeof(*x))
224294
225295void test_strings () {
226296 char buf [200 ];
@@ -397,6 +467,114 @@ void test_strings() {
397467 snprintf (buf , sizeof (buf ), fmt , 42 );
398468 TEST_STR (buf , "0002a" );
399469
470+ #ifdef _WIN32
471+ TEST_INT (_scprintf ("%d" , 12345 ), 5 );
472+ TEST_INT (_vscprintf_wrap ("%d" , 12345 ), 5 );
473+ #endif
474+
475+ wchar_t wbuf [200 ], wbuf2 [5 ];
476+ int ret ;
477+ fill_wchar (wbuf , '#' , ARRAYLEN (wbuf ));
478+ ret = swprintf (wbuf , ARRAYLEN (wbuf ), L"%d" , 42 );
479+ TEST_INT (ret , 2 );
480+ TEST_WSTR (wbuf , L"42" );
481+ TEST_INT (wbuf [ARRAYLEN (wbuf )- 1 ], '#' );
482+
483+ fill_wchar (wbuf , '#' , ARRAYLEN (wbuf ));
484+ ret = vswprintf_wrap (wbuf , ARRAYLEN (wbuf ), L"%d" , 42 );
485+ TEST_INT (ret , 2 );
486+ TEST_WSTR (wbuf , L"42" );
487+ TEST_INT (wbuf [ARRAYLEN (wbuf )- 1 ], '#' );
488+
489+ fill_wchar (wbuf2 , '#' , ARRAYLEN (wbuf2 ));
490+ ret = swprintf (wbuf2 , ARRAYLEN (wbuf2 ), L"%d" , 12345 );
491+ TEST_INT (ret , -1 );
492+ #ifndef __GLIBC__
493+ // On overflow, glibc doesn't seem to null terminate the array.
494+ // https://sourceware.org/bugzilla/show_bug.cgi?id=27857, fixed in
495+ // glibc 2.37.
496+ TEST_INT (wbuf2 [ARRAYLEN (wbuf2 )- 1 ], '\0' );
497+ #endif
498+ wbuf2 [ARRAYLEN (wbuf2 )- 1 ] = '\0' ;
499+ TEST_WSTR (wbuf2 , L"1234" );
500+
501+ #ifdef _WIN32
502+ #ifdef __cplusplus
503+ fill_wchar (wbuf , '#' , ARRAYLEN (wbuf ));
504+ ret = swprintf (wbuf , L"%d" , 42 );
505+ TEST_WSTR (wbuf , L"42" );
506+ TEST_INT (ret , 2 );
507+ TEST_INT (wbuf [ARRAYLEN (wbuf )- 1 ], '#' );
508+
509+ fill_wchar (wbuf , '#' , ARRAYLEN (wbuf ));
510+ ret = vswprintf_overload_wrap (wbuf , L"%d" , 42 );
511+ TEST_WSTR (wbuf , L"42" );
512+ TEST_INT (ret , 2 );
513+ TEST_INT (wbuf [ARRAYLEN (wbuf )- 1 ], '#' );
514+ #endif
515+
516+ fill_wchar (wbuf , '#' , ARRAYLEN (wbuf ));
517+ ret = _swprintf (wbuf , L"%d" , 42 );
518+ TEST_WSTR (wbuf , L"42" );
519+ TEST_INT (ret , 2 );
520+ TEST_INT (wbuf [ARRAYLEN (wbuf )- 1 ], '#' );
521+
522+ fill_wchar (wbuf , '#' , ARRAYLEN (wbuf ));
523+ ret = _vswprintf_wrap (wbuf , L"%d" , 42 );
524+ TEST_WSTR (wbuf , L"42" );
525+ TEST_INT (ret , 2 );
526+ TEST_INT (wbuf [ARRAYLEN (wbuf )- 1 ], '#' );
527+
528+ fill_wchar (wbuf2 , '#' , ARRAYLEN (wbuf2 ));
529+ ret = _snwprintf (wbuf2 , ARRAYLEN (wbuf2 ), L"%d" , 12345 );
530+ TEST_INT (ret , 5 );
531+ // On overflow, _snwprintf doesn't null terminate.
532+ TEST_INT (wbuf2 [ARRAYLEN (wbuf2 )- 1 ], '5' );
533+ wbuf2 [ARRAYLEN (wbuf2 )- 1 ] = '\0' ;
534+ TEST_WSTR (wbuf2 , L"1234" );
535+
536+ fill_wchar (wbuf2 , '#' , ARRAYLEN (wbuf2 ));
537+ ret = _snwprintf (wbuf2 , ARRAYLEN (wbuf2 ), L"%d" , 123456 );
538+ TEST_INT (ret , -1 );
539+ // On overflow, _snwprintf doesn't null terminate.
540+ TEST_INT (wbuf2 [ARRAYLEN (wbuf2 )- 1 ], '5' );
541+ wbuf2 [ARRAYLEN (wbuf2 )- 1 ] = '\0' ;
542+ TEST_WSTR (wbuf2 , L"1234" );
543+
544+ fill_wchar (wbuf2 , '#' , ARRAYLEN (wbuf2 ));
545+ ret = _vsnwprintf_wrap (wbuf2 , ARRAYLEN (wbuf2 ), L"%d" , 12345 );
546+ TEST_INT (ret , 5 );
547+ // On overflow, _vsnwprintf doesn't null terminate.
548+ TEST_INT (wbuf2 [ARRAYLEN (wbuf2 )- 1 ], '5' );
549+ wbuf2 [ARRAYLEN (wbuf2 )- 1 ] = '\0' ;
550+ TEST_WSTR (wbuf2 , L"1234" );
551+
552+ #ifdef __MINGW32__
553+ fill_wchar (wbuf2 , '#' , ARRAYLEN (wbuf2 ));
554+ ret = snwprintf (wbuf2 , ARRAYLEN (wbuf2 ), L"%d" , 123456 );
555+ TEST_INT (ret , 6 );
556+ // On overflow, snwprintf null terminates.
557+ TEST_INT (wbuf2 [ARRAYLEN (wbuf2 )- 1 ], '\0' );
558+ wbuf2 [ARRAYLEN (wbuf2 )- 1 ] = '\0' ;
559+ TEST_WSTR (wbuf2 , L"1234" );
560+
561+ TEST_INT (snwprintf (NULL , 0 , L"%d" , 123456 ), 6 );
562+
563+ fill_wchar (wbuf2 , '#' , ARRAYLEN (wbuf2 ));
564+ ret = vsnwprintf_wrap (wbuf2 , ARRAYLEN (wbuf2 ), L"%d" , 123456 );
565+ TEST_INT (ret , 6 );
566+ // On overflow, vsnwprintf null terminates.
567+ TEST_INT (wbuf2 [ARRAYLEN (wbuf2 )- 1 ], '\0' );
568+ wbuf2 [ARRAYLEN (wbuf2 )- 1 ] = '\0' ;
569+ TEST_WSTR (wbuf2 , L"1234" );
570+
571+ TEST_INT (vsnwprintf_wrap (NULL , 0 , L"%d" , 123456 ), 6 );
572+ #endif
573+
574+ TEST_INT (_scwprintf (L"%d" , 123456 ), 6 );
575+ TEST_INT (_vscwprintf_wrap (L"%d" , 123456 ), 6 );
576+ #endif
577+
400578 uint64_t val0 , val1 , val2 , val3 , val4 , val5 , val6 , val7 , val8 , val9 ;
401579 if (sscanf ("baadf00dcafe baadf00dcaff baadf00dcb00 baadf00dcb01 baadf00dcb02 baadf00dcb03 baadf00dcb04 baadf00dcb05 baadf00dcb06 baadf00dcb07" , "%" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 " %" SCNx64 , & val0 , & val1 , & val2 , & val3 , & val4 , & val5 , & val6 , & val7 , & val8 , & val9 ) != 10 ) {
402580 fails ++ ;
0 commit comments