summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--doc/posix-functions/swprintf.texi10
-rw-r--r--lib/vasnprintf.c34
-rw-r--r--m4/vasnprintf.m43
-rw-r--r--modules/vasnwprintf1
5 files changed, 51 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 53ba9040c6..e83875f2ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2023-03-19 Bruno Haible <bruno@clisp.org>
+ vasnwprintf: Fix test failures on musl libc.
+ * m4/vasnprintf.m4 (gl_PREREQ_VASNWPRINTF): Invoke gl_MUSL_LIBC.
+ * lib/vasnprintf.c (VASNPRINTF): On musl libc, when WIDE_CHAR_VERSION,
+ - force pad_ourselves to be 1,
+ - don't use %n.
+ Fix zero-padding when the result starts with a prefix "0x" or "0b".
+ * modules/vasnwprintf (Files): Add musl.m4.
+ * doc/posix-functions/swprintf.texi: Mention two musl libc bugs.
+
+2023-03-19 Bruno Haible <bruno@clisp.org>
+
vasnwprintf: Fix module dependencies.
* modules/vasnwprintf (Depends-on): Add wmemcpy, wmemset.
* modules/vasnwprintf-tests (Depends-on): Add wmemcmp.
diff --git a/doc/posix-functions/swprintf.texi b/doc/posix-functions/swprintf.texi
index 906ee521aa..a87bc06c86 100644
--- a/doc/posix-functions/swprintf.texi
+++ b/doc/posix-functions/swprintf.texi
@@ -26,11 +26,21 @@ This function does not support the @samp{n} directive on some platforms:
glibc when used with @code{_FORTIFY_SOURCE >= 2} (set by default on Ubuntu),
macOS 11.1, MSVC 14.
@item
+This function sometimes returns a wrong value through the @samp{n} directive
+on some platforms:
+@c https://www.openwall.com/lists/musl/2023/03/19/1
+musl libc 1.2.3.
+@item
On Windows and 32-bit AIX platforms, @code{wchar_t} is a 16-bit type and therefore cannot
accommodate all Unicode characters.
@item
On Windows, this function does not take a buffer size as second argument.
@item
+This function ignores the minimum field width in the @samp{lc} directive
+on some platforms:
+@c https://www.openwall.com/lists/musl/2023/03/20/1
+musl libc 1.2.3.
+@item
This function does not support the @samp{b} directive, required by ISO C23,
on some platforms:
glibc 2.34, musl libc, macOS 12.5, FreeBSD 13.1, NetBSD 9.0, OpenBSD 7.2,
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index c2f10cb0c4..50ff2e64dd 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -4932,7 +4932,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
{
arg_type type = a.arg[dp->arg_index].type;
int flags = dp->flags;
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int has_width;
#endif
#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
@@ -4947,7 +4947,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#else
# define prec_ourselves 0
#endif
-#if NEED_PRINTF_FLAG_LEFTADJUST
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST
# define pad_ourselves 1
#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
int pad_ourselves;
@@ -4964,7 +4964,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
TCHAR_T *tmp;
#endif
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 0;
#endif
#if !USE_SNPRINTF || WIDE_CHAR_VERSION || !HAVE_SNPRINTF_RETVAL_C99 || USE_MSVC__SNPRINTF || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
@@ -4995,7 +4995,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
width = xsum (xtimes (width, 10), *digitp++ - '0');
while (digitp != dp->width_end);
}
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
has_width = 1;
#endif
}
@@ -5050,7 +5050,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#endif
/* Decide whether to perform the padding ourselves. */
-#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
+#if !((WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST) && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
switch (dp->conversion)
{
# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
@@ -5210,7 +5210,8 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
|| (defined __APPLE__ && defined __MACH__) \
|| defined __OpenBSD__ \
|| defined __ANDROID__ \
- || (defined _WIN32 && ! defined __CYGWIN__))
+ || (defined _WIN32 && ! defined __CYGWIN__)) \
+ || (WIDE_CHAR_VERSION && MUSL_LIBC)
/* We can avoid passing %n and instead rely on SNPRINTF's
return value if
- !WIDE_CHAR_VERSION, because if WIDE_CHAR_VERSION,
@@ -5263,6 +5264,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
- Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
allows us to recognize the case of an insufficient
buffer size: it returns -1 in this case. */
+ /* Additionally, in the WIDE_CHAR_VERSION case, we cannot use %n
+ on musl libc because we would run into an swprintf() bug.
+ See <https://www.openwall.com/lists/musl/2023/03/19/1>. */
fbp[1] = '\0';
# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */
fbp[1] = '%';
@@ -5768,7 +5772,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* Here count <= allocated - length. */
/* Perform padding. */
-#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+#if (WIDE_CHAR_VERSION && MUSL_LIBC) || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
if (pad_ourselves && has_width)
{
size_t w;
@@ -5827,6 +5831,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
|| (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
pad_ptr = NULL;
+ else
+ /* Do the zero-padding after the "0x" or
+ "0b" prefix, not before. */
+ if (p - rp >= 2
+ && *rp == '0'
+ && (((dp->conversion == 'a'
+ || dp->conversion == 'x')
+ && rp[1] == 'x')
+ || ((dp->conversion == 'A'
+ || dp->conversion == 'X')
+ && rp[1] == 'X')
+ || (dp->conversion == 'b'
+ && rp[1] == 'b')
+ || (dp->conversion == 'B'
+ && rp[1] == 'B')))
+ pad_ptr += 2;
}
/* The generated string now extends from rp to p,
with the zero padding insertion point being at
diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4
index b868aed08b..8e582dd791 100644
--- a/m4/vasnprintf.m4
+++ b/m4/vasnprintf.m4
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 41
+# vasnprintf.m4 serial 42
dnl Copyright (C) 2002-2004, 2006-2023 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -96,6 +96,7 @@ AC_DEFUN_ONCE([gl_PREREQ_VASNWPRINTF],
[
AC_CHECK_FUNCS([wcsnlen mbrtowc])
AC_CHECK_DECLS([_snwprintf], , , [[#include <stdio.h>]])
+ gl_MUSL_LIBC
gl_PREREQ_VASNXPRINTF
])
diff --git a/modules/vasnwprintf b/modules/vasnwprintf
index 6c7d63a5f6..07a078696c 100644
--- a/modules/vasnwprintf
+++ b/modules/vasnwprintf
@@ -21,6 +21,7 @@ m4/vasnprintf.m4
m4/printf.m4
m4/math_h.m4
m4/exponentd.m4
+m4/musl.m4
Depends-on:
stdio