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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
+
+ vasnprintf: Refactor.
+ * lib/vasnprintf.c (VASNPRINTF) [!DCHAR_IS_TCHAR]: Reduce the scope of
+ the tmpsrc variables.
+
2024-06-18 Paul Eggert <[email protected]>
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 <[email protected]>
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 <[email protected]>
+
+ 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
+ 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