In the conversion from TCHAR_T[] to DCHAR_T[] in vasnprintf.c, there is an optimized loop for the case that the directive's result is entirely ASCII.
There was a bug in this logic: On glibc systems, the result of the %Id directive uses alternate digits (used in Farsi and some Arabic locales), and these are not ASCII. I found this by running the vasnwprintf unit test (test-vasnwprintf-posix3) in a testdir configured with ac_cv_func_swprintf=no. The code paths for the case of vasnwprintf on old platforms and of unistdio/u*-vasnprintf are similar. 2023-03-21 Bruno Haible <br...@clisp.org> unistdio/u*-vasnprintf: Fix conversion of %Id directive result. * lib/vasnprintf.c (VASNPRINTF): Don't assume that snprintf's result is entirely ASCII if the directive contain the glibc 'I' flag. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index bd13002e98..8e6596df2f 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -5836,11 +5836,13 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #if !DCHAR_IS_TCHAR /* Convert from TCHAR_T[] to DCHAR_T[]. */ - if (dp->conversion == 'c' || dp->conversion == 's') + if (dp->conversion == 'c' || dp->conversion == 's' +# if __GLIBC__ >= 2 && !defined __UCLIBC__ + || (flags & FLAG_LOCALIZED) +# endif + ) { - /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING - TYPE_WIDE_STRING. - The result string is not certainly ASCII. */ + /* The result string is not guaranteed to be ASCII. */ const TCHAR_T *tmpsrc; DCHAR_T *tmpdst; size_t tmpdst_len;