In lib/vasnprintf.c the first two invocations of DCHAR_MBSNLEN w = DCHAR_MBSNLEN (result + length, count);
look wrong, because the memory beyond result + length has not been initialized at that point. This code handles the %ls and %lc directives. The platforms where this code is enabled are Solaris and MSVC. And indeed, once I add tests for the %ls and %lc directives, I see them crash. On Solaris 11.4: FAIL: unistdio/test-u16-vasnprintf2.sh ====================================== ../../gltests/unistdio/test-u16-vasnprintf2.sh: line 20: 3887: Memory fault(coredump) ../../build-aux/test-driver: line 116: 3885: Memory fault(coredump) FAIL unistdio/test-u16-vasnprintf2.sh (exit status: 267) FAIL: unistdio/test-u16-vasnprintf3.sh ====================================== ../../gltests/unistdio/test-u16-vasnprintf3.sh: line 20: 3895: Memory fault(coredump) ../../build-aux/test-driver: line 116: 3893: Memory fault(coredump) FAIL unistdio/test-u16-vasnprintf3.sh (exit status: 267) FAIL: unistdio/test-u32-vasnprintf3.sh ====================================== ../../gltests/unistdio/test-u32-vasnprintf3.c:120: assertion 'u32_strcmp (result, expected) == 0' failed ../../gltests/unistdio/test-u32-vasnprintf3.sh: line 20: 3915: Abort(coredump) ../../build-aux/test-driver: line 116: 3913: Abort(coredump) FAIL unistdio/test-u32-vasnprintf3.sh (exit status: 262) FAIL: unistdio/test-u8-vasnprintf2.sh ===================================== ../../gltests/unistdio/test-u8-vasnprintf2.sh: line 20: 3927: Memory fault(coredump) ../../build-aux/test-driver: line 116: 3925: Memory fault(coredump) FAIL unistdio/test-u8-vasnprintf2.sh (exit status: 267) FAIL: unistdio/test-u8-vasnprintf3.sh ===================================== ../../gltests/unistdio/test-u8-vasnprintf3.sh: line 20: 3935: Memory fault(coredump) ../../build-aux/test-driver: line 116: 3933: Memory fault(coredump) FAIL unistdio/test-u8-vasnprintf3.sh (exit status: 267) FAIL: unistdio/test-ulc-vasnprintf3.sh ====================================== ../../gltests/unistdio/test-ulc-vasnprintf3.sh: line 20: 3955: Memory fault(coredump) ../../build-aux/test-driver: line 116: 3953: Memory fault(coredump) FAIL unistdio/test-ulc-vasnprintf3.sh (exit status: 267) And similarly on MSVC 14.30. The following patches fix the problem and add the unit tests. 2024-06-18 Bruno Haible <br...@clisp.org> u*-vasnprintf tests: Add tests of %ls directive. * tests/unistdio/test-u8-vasnprintf2.c (test_function): Add tests of the %ls directive with non-ASCII argument. * tests/unistdio/test-u8-vasnprintf3.c (test_function): Likewise. * tests/unistdio/test-u16-vasnprintf2.c (test_function): Likewise. * tests/unistdio/test-u16-vasnprintf3.c (test_function): Likewise. * tests/unistdio/test-u32-vasnprintf2.c (test_function): Likewise. * tests/unistdio/test-u32-vasnprintf3.c (test_function): Likewise. * tests/unistdio/test-ulc-vasnprintf2.c (test_function): Likewise. * tests/unistdio/test-ulc-vasnprintf3.c (test_function): Likewise. u*-vasnprintf: Fix handling of %ls, %lc directives on Solaris, MSVC. * lib/vasnprintf.c (VASNPRINTF): When implementing the %ls, %lc directives ourselves: Rename variable 'characters' to 'bytes'. Also count characters, if necessary for the width handling. Fix DCHAR_MBSNLEN invocation. 2024-06-18 Bruno Haible <br...@clisp.org> vasnprintf: Refactor. * lib/vasnprintf.c (VASNPRINTF) [!DCHAR_IS_TCHAR]: Reduce the scope of the tmpsrc variables.
>From ef47dacd8bc1088110c09aac17ce9099dc7b05b5 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Tue, 18 Jun 2024 03:16:17 +0200 Subject: [PATCH 1/3] vasnprintf: Refactor. * lib/vasnprintf.c (VASNPRINTF) [!DCHAR_IS_TCHAR]: Reduce the scope of the tmpsrc variables. --- ChangeLog | 6 +++ lib/vasnprintf.c | 130 +++++++++++++++++++++++++---------------------- 2 files changed, 74 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d5c743711..4b1ee34b9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-06-18 Bruno Haible <br...@clisp.org> + + vasnprintf: Refactor. + * lib/vasnprintf.c (VASNPRINTF) [!DCHAR_IS_TCHAR]: Reduce the scope of + the tmpsrc variables. + 2024-06-18 Paul Eggert <egg...@cs.ucla.edu> nstrftime: tweak volatile access diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 0242dd3f55..f9580f7ef4 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -3190,7 +3190,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, # if !DCHAR_IS_TCHAR /* This code assumes that TCHAR_T is 'char'. */ static_assert (sizeof (TCHAR_T) == 1); - TCHAR_T *tmpsrc; DCHAR_T *tmpdst; size_t tmpdst_len; # endif @@ -3266,50 +3265,54 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, # endif # if !DCHAR_IS_TCHAR - /* Convert the string into a piece of temporary memory. */ - tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T)); - if (tmpsrc == NULL) - goto out_of_memory; { - TCHAR_T *tmpptr = tmpsrc; - size_t remaining; + TCHAR_T *tmpsrc; + + /* Convert the string into a piece of temporary memory. */ + tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T)); + if (tmpsrc == NULL) + goto out_of_memory; + { + TCHAR_T *tmpptr = tmpsrc; + size_t remaining; # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - mbszero (&state); + mbstate_t state; + mbszero (&state); # endif - for (remaining = characters; remaining > 0; ) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; + for (remaining = characters; remaining > 0; ) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; - if (*arg == 0) - abort (); - count = local_wcrtomb (cbuf, *arg, &state); - if (count <= 0) - /* Inconsistency. */ - abort (); - memcpy (tmpptr, cbuf, count); - tmpptr += count; - arg++; - remaining -= count; + if (*arg == 0) + abort (); + count = local_wcrtomb (cbuf, *arg, &state); + if (count <= 0) + /* Inconsistency. */ + abort (); + memcpy (tmpptr, cbuf, count); + tmpptr += count; + arg++; + remaining -= count; + } + if (!(arg == arg_end)) + abort (); + } + + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + tmpdst = + DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, characters, + NULL, + NULL, &tmpdst_len); + if (tmpdst == NULL) + { + free (tmpsrc); + goto fail_with_errno; } - if (!(arg == arg_end)) - abort (); + free (tmpsrc); } - - /* Convert from TCHAR_T[] to DCHAR_T[]. */ - tmpdst = - DCHAR_CONV_FROM_ENCODING (locale_charset (), - iconveh_question_mark, - tmpsrc, characters, - NULL, - NULL, &tmpdst_len); - if (tmpdst == NULL) - { - free (tmpsrc); - goto fail_with_errno; - } - free (tmpsrc); # endif if (has_width) @@ -3459,7 +3462,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, # if !DCHAR_IS_TCHAR /* This code assumes that TCHAR_T is 'char'. */ static_assert (sizeof (TCHAR_T) == 1); - TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */ DCHAR_T *tmpdst; size_t tmpdst_len; # endif @@ -3493,32 +3495,36 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, # endif # if !DCHAR_IS_TCHAR - /* Convert the string into a piece of temporary memory. */ - if (characters > 0) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; + { + TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */ + + /* Convert the string into a piece of temporary memory. */ + if (characters > 0) + { + char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ + int count; # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - mbszero (&state); + mbstate_t state; + mbszero (&state); # endif - count = local_wcrtomb (cbuf, arg, &state); - if (count <= 0) - /* Inconsistency. */ - abort (); - memcpy (tmpsrc, cbuf, count); - } + count = local_wcrtomb (cbuf, arg, &state); + if (count <= 0) + /* Inconsistency. */ + abort (); + memcpy (tmpsrc, cbuf, count); + } - /* Convert from TCHAR_T[] to DCHAR_T[]. */ - tmpdst = - DCHAR_CONV_FROM_ENCODING (locale_charset (), - iconveh_question_mark, - tmpsrc, characters, - NULL, - NULL, &tmpdst_len); - if (tmpdst == NULL) - goto fail_with_errno; + /* Convert from TCHAR_T[] to DCHAR_T[]. */ + tmpdst = + DCHAR_CONV_FROM_ENCODING (locale_charset (), + iconveh_question_mark, + tmpsrc, characters, + NULL, + NULL, &tmpdst_len); + if (tmpdst == NULL) + goto fail_with_errno; + } # endif if (has_width) -- 2.34.1
>From 0823ace3be6e33961ece9da45da084ab37d30277 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Tue, 18 Jun 2024 19:18:27 +0200 Subject: [PATCH 2/3] u*-vasnprintf: Fix handling of %ls, %lc directives on Solaris, MSVC. * lib/vasnprintf.c (VASNPRINTF): When implementing the %ls, %lc directives ourselves: Rename variable 'characters' to 'bytes'. Also count characters, if necessary for the width handling. Fix DCHAR_MBSNLEN invocation. --- ChangeLog | 8 ++++++ lib/vasnprintf.c | 74 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b1ee34b9d..5d5acb7de9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2024-06-18 Bruno Haible <br...@clisp.org> + + u*-vasnprintf: Fix handling of %ls, %lc directives on Solaris, MSVC. + * lib/vasnprintf.c (VASNPRINTF): When implementing the %ls, %lc + directives ourselves: Rename variable 'characters' to 'bytes'. Also + count characters, if necessary for the width handling. Fix + DCHAR_MBSNLEN invocation. + 2024-06-18 Bruno Haible <br...@clisp.org> vasnprintf: Refactor. diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index f9580f7ef4..059c1a9cb3 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -3186,7 +3186,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; const wchar_t *arg_end; + size_t bytes; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR size_t characters; +# endif # if !DCHAR_IS_TCHAR /* This code assumes that TCHAR_T is 'char'. */ static_assert (sizeof (TCHAR_T) == 1); @@ -3204,7 +3207,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, mbszero (&state); # endif arg_end = arg; + bytes = 0; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR characters = 0; +# endif while (precision > 0) { char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ @@ -3220,7 +3226,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (precision < (unsigned int) count) break; arg_end++; - characters += count; + bytes += count; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR + characters += mbsnlen (cbuf, count); +# endif precision -= count; } } @@ -3237,7 +3246,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, mbszero (&state); # endif arg_end = arg; + bytes = 0; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR characters = 0; +# endif for (;;) { char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ @@ -3251,7 +3263,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Cannot convert. */ goto fail_with_EILSEQ; arg_end++; - characters += count; + bytes += count; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR + characters += mbsnlen (cbuf, count); +# endif } } # if DCHAR_IS_TCHAR @@ -3259,8 +3274,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, { /* Use the entire string. */ arg_end = arg + local_wcslen (arg); - /* The number of bytes doesn't matter. */ + /* The number of bytes and characters doesn't matter, + because !has_width and therefore width==0. */ + bytes = 0; +# if ENABLE_UNISTDIO characters = 0; +# endif } # endif @@ -3269,7 +3288,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, TCHAR_T *tmpsrc; /* Convert the string into a piece of temporary memory. */ - tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T)); + tmpsrc = (TCHAR_T *) malloc (bytes * sizeof (TCHAR_T)); if (tmpsrc == NULL) goto out_of_memory; { @@ -3279,7 +3298,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, mbstate_t state; mbszero (&state); # endif - for (remaining = characters; remaining > 0; ) + for (remaining = bytes; remaining > 0; ) { char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ int count; @@ -3303,7 +3322,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, tmpdst = DCHAR_CONV_FROM_ENCODING (locale_charset (), iconveh_question_mark, - tmpsrc, characters, + tmpsrc, bytes, NULL, NULL, &tmpdst_len); if (tmpdst == NULL) @@ -3321,11 +3340,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Outside POSIX, it's preferable to compare the width against the number of _characters_ of the converted value. */ - w = DCHAR_MBSNLEN (result + length, characters); +# if DCHAR_IS_TCHAR + w = characters; +# else + w = DCHAR_MBSNLEN (tmpdst, tmpdst_len); +# endif # else /* The width is compared against the number of _bytes_ of the converted value, says POSIX. */ - w = characters; + w = bytes; # endif } else @@ -3349,8 +3372,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, mbstate_t state; mbszero (&state); # endif - ENSURE_ALLOCATION (xsum (length, characters)); - for (remaining = characters; remaining > 0; ) + ENSURE_ALLOCATION (xsum (length, bytes)); + for (remaining = bytes; remaining > 0; ) { char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ int count; @@ -3458,7 +3481,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* %lc in vasnprintf. See the specification of fprintf. */ { wchar_t arg = (wchar_t) a.arg[dp->arg_index].a.a_wide_char; + size_t bytes; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR size_t characters; +# endif # if !DCHAR_IS_TCHAR /* This code assumes that TCHAR_T is 'char'. */ static_assert (sizeof (TCHAR_T) == 1); @@ -3472,7 +3498,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, # endif { /* Count the number of bytes. */ - characters = 0; char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ int count; # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t @@ -3484,13 +3509,20 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (count < 0) /* Cannot convert. */ goto fail_with_EILSEQ; - characters = count; + bytes = count; +# if ENABLE_UNISTDIO && DCHAR_IS_TCHAR + characters = mbsnlen (cbuf, count); +# endif } # if DCHAR_IS_TCHAR else { - /* The number of bytes doesn't matter. */ + /* The number of bytes and characters doesn't matter, + because !has_width and therefore width==0. */ + bytes = 0; +# if ENABLE_UNISTDIO characters = 0; +# endif } # endif @@ -3499,7 +3531,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, TCHAR_T tmpsrc[64]; /* Assume MB_CUR_MAX <= 64. */ /* Convert the string into a piece of temporary memory. */ - if (characters > 0) + if (bytes > 0) { char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ int count; @@ -3519,7 +3551,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, tmpdst = DCHAR_CONV_FROM_ENCODING (locale_charset (), iconveh_question_mark, - tmpsrc, characters, + tmpsrc, bytes, NULL, NULL, &tmpdst_len); if (tmpdst == NULL) @@ -3533,11 +3565,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, /* Outside POSIX, it's preferable to compare the width against the number of _characters_ of the converted value. */ - w = DCHAR_MBSNLEN (result + length, characters); +# if DCHAR_IS_TCHAR + w = characters; +# else + w = DCHAR_MBSNLEN (tmpdst, tmpdst_len); +# endif # else /* The width is compared against the number of _bytes_ of the converted value, says POSIX. */ - w = characters; + w = bytes; # endif } else @@ -3556,8 +3592,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, if (has_width) { /* We know the number of bytes in advance. */ - ENSURE_ALLOCATION (xsum (length, characters)); - if (characters > 0) + ENSURE_ALLOCATION (xsum (length, bytes)); + if (bytes > 0) { int count; # if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t -- 2.34.1
From 937c40c83e3286d7d6e20c6c7f6fbddc49160a3a Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Tue, 18 Jun 2024 19:21:53 +0200 Subject: [PATCH 3/3] u*-vasnprintf tests: Add tests of %ls directive. * tests/unistdio/test-u8-vasnprintf2.c (test_function): Add tests of the %ls directive with non-ASCII argument. * tests/unistdio/test-u8-vasnprintf3.c (test_function): Likewise. * tests/unistdio/test-u16-vasnprintf2.c (test_function): Likewise. * tests/unistdio/test-u16-vasnprintf3.c (test_function): Likewise. * tests/unistdio/test-u32-vasnprintf2.c (test_function): Likewise. * tests/unistdio/test-u32-vasnprintf3.c (test_function): Likewise. * tests/unistdio/test-ulc-vasnprintf2.c (test_function): Likewise. * tests/unistdio/test-ulc-vasnprintf3.c (test_function): Likewise. --- ChangeLog | 11 +++++ tests/unistdio/test-u16-vasnprintf2.c | 63 +++++++++++++++++++++++++++ tests/unistdio/test-u16-vasnprintf3.c | 63 +++++++++++++++++++++++++++ tests/unistdio/test-u32-vasnprintf2.c | 63 +++++++++++++++++++++++++++ tests/unistdio/test-u32-vasnprintf3.c | 63 +++++++++++++++++++++++++++ tests/unistdio/test-u8-vasnprintf2.c | 48 ++++++++++++++++++++ tests/unistdio/test-u8-vasnprintf3.c | 48 ++++++++++++++++++++ tests/unistdio/test-ulc-vasnprintf2.c | 44 +++++++++++++++++++ tests/unistdio/test-ulc-vasnprintf3.c | 44 +++++++++++++++++++ 9 files changed, 447 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5d5acb7de9..43b8424b6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2024-06-18 Bruno Haible <br...@clisp.org> + u*-vasnprintf tests: Add tests of %ls directive. + * tests/unistdio/test-u8-vasnprintf2.c (test_function): Add tests of + the %ls directive with non-ASCII argument. + * tests/unistdio/test-u8-vasnprintf3.c (test_function): Likewise. + * tests/unistdio/test-u16-vasnprintf2.c (test_function): Likewise. + * tests/unistdio/test-u16-vasnprintf3.c (test_function): Likewise. + * tests/unistdio/test-u32-vasnprintf2.c (test_function): Likewise. + * tests/unistdio/test-u32-vasnprintf3.c (test_function): Likewise. + * tests/unistdio/test-ulc-vasnprintf2.c (test_function): Likewise. + * tests/unistdio/test-ulc-vasnprintf3.c (test_function): Likewise. + u*-vasnprintf: Fix handling of %ls, %lc directives on Solaris, MSVC. * lib/vasnprintf.c (VASNPRINTF): When implementing the %ls, %lc directives ourselves: Rename variable 'characters' to 'bytes'. Also diff --git a/tests/unistdio/test-u16-vasnprintf2.c b/tests/unistdio/test-u16-vasnprintf2.c index c0da1e00cf..4c061c6684 100644 --- a/tests/unistdio/test-u16-vasnprintf2.c +++ b/tests/unistdio/test-u16-vasnprintf2.c @@ -87,6 +87,69 @@ test_function (uint16_t * (*my_asnprintf) (uint16_t *, size_t *, const char *, . free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\351t\351rog\351n\351it\351"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + } } static uint16_t * diff --git a/tests/unistdio/test-u16-vasnprintf3.c b/tests/unistdio/test-u16-vasnprintf3.c index f1156791bc..d5924f8bad 100644 --- a/tests/unistdio/test-u16-vasnprintf3.c +++ b/tests/unistdio/test-u16-vasnprintf3.c @@ -87,6 +87,69 @@ test_function (uint16_t * (*my_asnprintf) (uint16_t *, size_t *, const char *, . free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\303\251t\303\251rog\303\251n\303\251it\303\251"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + uint16_t *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + static const uint16_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u16_strcmp (result, expected) == 0); + ASSERT (length == u16_strlen (result)); + free (result); + } + } } static uint16_t * diff --git a/tests/unistdio/test-u32-vasnprintf2.c b/tests/unistdio/test-u32-vasnprintf2.c index 64c91f0c46..70336c7c49 100644 --- a/tests/unistdio/test-u32-vasnprintf2.c +++ b/tests/unistdio/test-u32-vasnprintf2.c @@ -87,6 +87,69 @@ test_function (uint32_t * (*my_asnprintf) (uint32_t *, size_t *, const char *, . free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\351t\351rog\351n\351it\351"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + } } static uint32_t * diff --git a/tests/unistdio/test-u32-vasnprintf3.c b/tests/unistdio/test-u32-vasnprintf3.c index 9e4eb11f92..816eb9fd8b 100644 --- a/tests/unistdio/test-u32-vasnprintf3.c +++ b/tests/unistdio/test-u32-vasnprintf3.c @@ -87,6 +87,69 @@ test_function (uint32_t * (*my_asnprintf) (uint32_t *, size_t *, const char *, . free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\303\251t\303\251rog\303\251n\303\251it\303\251"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { 'h', 0x00e9, 't', 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, + 'i', 't', 0x00e9, ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + uint32_t *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + static const uint32_t expected[] = + { ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'h', 0x00e9, 't', + 0x00e9, 'r', 'o', 'g', 0x00e9, 'n', 0x00e9, 'i', 't', 0x00e9, + ' ', '3', '3', 0 + }; + ASSERT (result != NULL); + ASSERT (u32_strcmp (result, expected) == 0); + ASSERT (length == u32_strlen (result)); + free (result); + } + } } static uint32_t * diff --git a/tests/unistdio/test-u8-vasnprintf2.c b/tests/unistdio/test-u8-vasnprintf2.c index aa11e47437..3c0a00f13f 100644 --- a/tests/unistdio/test-u8-vasnprintf2.c +++ b/tests/unistdio/test-u8-vasnprintf2.c @@ -77,6 +77,54 @@ test_function (uint8_t * (*my_asnprintf) (uint8_t *, size_t *, const char *, ... free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\351t\351rog\351n\351it\351"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = "h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = " h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = "h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = " h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + } } static uint8_t * diff --git a/tests/unistdio/test-u8-vasnprintf3.c b/tests/unistdio/test-u8-vasnprintf3.c index 98b851aa27..72efa60ae6 100644 --- a/tests/unistdio/test-u8-vasnprintf3.c +++ b/tests/unistdio/test-u8-vasnprintf3.c @@ -77,6 +77,54 @@ test_function (uint8_t * (*my_asnprintf) (uint8_t *, size_t *, const char *, ... free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\303\251t\303\251rog\303\251n\303\251it\303\251"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = "h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = " h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = "h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + uint8_t *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + static const uint8_t expected[] = " h\303\251t\303\251rog\303\251n\303\251it\303\251 33"; + ASSERT (result != NULL); + ASSERT (u8_strcmp (result, expected) == 0); + ASSERT (length == u8_strlen (result)); + free (result); + } + } } static uint8_t * diff --git a/tests/unistdio/test-ulc-vasnprintf2.c b/tests/unistdio/test-ulc-vasnprintf2.c index 1904aa76f1..d91fa86e5a 100644 --- a/tests/unistdio/test-ulc-vasnprintf2.c +++ b/tests/unistdio/test-ulc-vasnprintf2.c @@ -214,6 +214,50 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\351t\351rog\351n\351it\351"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "h\351t\351rog\351n\351it\351 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " h\351t\351rog\351n\351it\351 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "h\351t\351rog\351n\351it\351 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " h\351t\351rog\351n\351it\351 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + } } static char * diff --git a/tests/unistdio/test-ulc-vasnprintf3.c b/tests/unistdio/test-ulc-vasnprintf3.c index 12ef2bfc66..7fc6171952 100644 --- a/tests/unistdio/test-ulc-vasnprintf3.c +++ b/tests/unistdio/test-ulc-vasnprintf3.c @@ -202,6 +202,50 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } } + + /* Test the support of the 'ls' conversion specifier for wide strings. */ + + { + const char *locale_string = "h\303\251t\303\251rog\303\251n\303\251it\303\251"; /* hétérogénéité */ + wchar_t wide_string[20]; + ASSERT (mbstowcs (wide_string, locale_string, SIZEOF (wide_string)) == 13); + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "h\303\251t\303\251rog\303\251n\303\251it\303\251 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* Width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%20ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " h\303\251t\303\251rog\303\251n\303\251it\303\251 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* FLAG_LEFT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%-20ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "h\303\251t\303\251rog\303\251n\303\251it\303\251 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* FLAG_ZERO: no effect. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%020ls %d", wide_string, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " h\303\251t\303\251rog\303\251n\303\251it\303\251 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + } } static char * -- 2.34.1