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

Reply via email to