[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
wcrtomb: Work around bug on Android 4.3
From: |
Bruno Haible |
Subject: |
wcrtomb: Work around bug on Android 4.3 |
Date: |
Sat, 26 Jan 2019 00:46:16 +0100 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-141-generic; KDE/5.18.0; x86_64; ; ) |
On Android 4.3, I'm seeing these test failures:
FAIL: test-snprintf-posix
=========================
../../gltests/test-snprintf-posix.h:2795: assertion 'memcmp (result,
"abcdefgh", i) == 0' failed
FAIL test-snprintf-posix (exit status: 139)
FAIL: test-sprintf-posix
========================
../../gltests/test-sprintf-posix.h:2781: assertion 'memcmp (result, "abcdefgh",
i) == 0' failed
FAIL test-sprintf-posix (exit status: 139)
FAIL: test-vsnprintf-posix
==========================
../../gltests/test-snprintf-posix.h:2795: assertion 'memcmp (result,
"abcdefgh", i) == 0' failed
FAIL test-vsnprintf-posix (exit status: 139)
FAIL: test-vsprintf-posix
=========================
../../gltests/test-sprintf-posix.h:2781: assertion 'memcmp (result, "abcdefgh",
i) == 0' failed
FAIL test-vsprintf-posix (exit status: 139)
The reason is that the wcrtomb() function is completely broken.
It converts, for example, the wide character L'a' to 0x01 (instead of 'a').
This patch provides a replacement wcrtomb().
Also, the tests of the wcrtomb module ought to have detected this bug.
Let me add tests for wcrtomb in the C locale (like Paul added tests for
mbrtowc in the C locale on 2016-04-09).
2019-01-25 Bruno Haible <address@hidden>
wcrtomb: Work around bug on Android 4.3.
* m4/wcrtomb.m4 (gl_FUNC_WCRTOMB): Test also whether wcrtomb works in
the C locale.
* lib/wcrtomb.c (wcrtomb): Provide alternate implementation for Android,
which does not have the 'wctomb' function.
* doc/posix-functions/wcrtomb.texi: Mention the Android bug.
* tests/test-wcrtomb.c (main): Accept argument '5'.
* tests/test-wcrtomb.sh: Add tests in the POSIX locale.
diff --git a/doc/posix-functions/wcrtomb.texi b/doc/posix-functions/wcrtomb.texi
index e3e7b57..4bdc50e 100644
--- a/doc/posix-functions/wcrtomb.texi
+++ b/doc/posix-functions/wcrtomb.texi
@@ -12,6 +12,9 @@ Portability problems fixed by Gnulib:
This function is missing on some platforms:
Minix 3.1.8, HP-UX 11.00, IRIX 6.5, Solaris 2.6, mingw, Interix 3.5.
@item
+This function produces wrong characters in the C locale on some platforms:
+Android 4.3.
address@hidden
This function returns 0 when the first argument is NULL in some locales on
some platforms:
AIX 4.3, OSF/1 5.1, Solaris 11.3.
@end itemize
diff --git a/lib/wcrtomb.c b/lib/wcrtomb.c
index 9fc40cf..8e56732 100644
--- a/lib/wcrtomb.c
+++ b/lib/wcrtomb.c
@@ -27,8 +27,8 @@
size_t
wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
{
- /* This implementation of wcrtomb on top of wctomb() supports only
- stateless encodings. ps must be in the initial state. */
+ /* This implementation of wcrtomb supports only stateless encodings.
+ ps must be in the initial state. */
if (ps != NULL && !mbsinit (ps))
{
errno = EINVAL;
@@ -40,10 +40,21 @@ wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
return 1;
else
{
+#if defined __ANDROID__
+ /* Implement consistently with mbrtowc(): through a 1:1 correspondence,
+ as in ISO-8859-1. */
+ if (wc >= 0 && wc <= 0xff)
+ {
+ *s = (unsigned char) wc;
+ return 1;
+ }
+#else
+ /* Implement on top of wctomb(). */
int ret = wctomb (s, wc);
if (ret >= 0)
return ret;
+#endif
else
{
errno = EILSEQ;
diff --git a/m4/wcrtomb.m4 b/m4/wcrtomb.m4
index f4f37f5..fec22f3 100644
--- a/m4/wcrtomb.m4
+++ b/m4/wcrtomb.m4
@@ -1,4 +1,4 @@
-# wcrtomb.m4 serial 13
+# wcrtomb.m4 serial 14
dnl Copyright (C) 2008-2019 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,7 +33,9 @@ AC_DEFUN([gl_FUNC_WCRTOMB],
else
if test $REPLACE_MBSTATE_T = 1; then
REPLACE_WCRTOMB=1
- else
+ fi
+ if test $REPLACE_WCRTOMB = 0; then
+ dnl On Android 4.3, wcrtomb produces wrong characters in the C locale.
dnl On AIX 4.3, OSF/1 5.1 and Solaris <= 11.3, wcrtomb (NULL, 0, NULL)
dnl sometimes returns 0 instead of 1.
AC_REQUIRE([AC_PROG_CC])
@@ -42,6 +44,45 @@ AC_DEFUN([gl_FUNC_WCRTOMB],
AC_REQUIRE([gt_LOCALE_JA])
AC_REQUIRE([gt_LOCALE_ZH_CN])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_CACHE_CHECK([whether wcrtomb works in the C locale],
+ [gl_cv_func_wcrtomb_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_SOURCE([[
+#include <string.h>
+#include <stdlib.h>
+/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
+ <wchar.h>.
+ BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
+ included before <wchar.h>. */
+#include <stddef.h>
+#include <stdio.h>
+#include <wchar.h>
+int main ()
+{
+ mbstate_t state;
+ char out[64];
+ int count;
+ memset (&state, 0, sizeof (state));
+ out[0] = 'x';
+ count = wcrtomb (out, L'a', &state);
+ return !(count == 1 && out[0] == 'a');
+}]])],
+ [gl_cv_func_wcrtomb_works=yes],
+ [gl_cv_func_wcrtomb_works=no],
+ [case "$host_os" in
+ # Guess no on Android.
+ linux*-android*) gl_cv_func_wcrtomb_works="guessing no";;
+ # Guess yes otherwise.
+ *) gl_cv_func_wcrtomb_works="guessing yes";;
+ esac
+ ])
+ ])
+ case "$gl_cv_func_wcrtomb_works" in
+ *yes) ;;
+ *) REPLACE_WCRTOMB=1 ;;
+ esac
+ fi
+ if test $REPLACE_WCRTOMB = 0; then
AC_CACHE_CHECK([whether wcrtomb return value is correct],
[gl_cv_func_wcrtomb_retval],
[
diff --git a/tests/test-wcrtomb.c b/tests/test-wcrtomb.c
index c4baf38..2f0b64b 100644
--- a/tests/test-wcrtomb.c
+++ b/tests/test-wcrtomb.c
@@ -156,6 +156,10 @@ main (int argc, char *argv[])
check_character (input + 3, 4);
}
return 0;
+
+ case '5':
+ /* C locale; tested above. */
+ return 0;
}
return 1;
diff --git a/tests/test-wcrtomb.sh b/tests/test-wcrtomb.sh
index 3eda8f3..c183505 100755
--- a/tests/test-wcrtomb.sh
+++ b/tests/test-wcrtomb.sh
@@ -32,4 +32,8 @@ if test $LOCALE_ZH_CN != none; then
|| exit 1
fi
+# Test in the POSIX locale.
+LC_ALL=C ./test-wcrtomb${EXEEXT} 5 || exit 1
+LC_ALL=POSIX ./test-wcrtomb${EXEEXT} 5 || exit 1
+
exit 0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- wcrtomb: Work around bug on Android 4.3,
Bruno Haible <=