From: Bruno Haible Date: Thu, 30 Mar 2023 21:12:50 +0000 (+0200) Subject: mbsrtowcs: Fix behaviour in the C locale. X-Git-Tag: v1.0~1542 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=63861afac8004becc3907993cd16b59a5bca5195;p=gnulib.git mbsrtowcs: Fix behaviour in the C locale. * m4/mbsrtowcs.m4 (gl_FUNC_MBSRTOWCS): Invoke gl_MBRTOWC_C_LOCALE. If mbrtowc is buggy in the C locale, override also mbsrtowcs. * modules/mbsrtowcs (Files): Add m4/mbrtowc.m4. * tests/test-mbsrtowcs.c (main): Add a test of the C locale, based on tests/test-mbrtowc.c. * tests/test-mbsrtowcs5.sh: New file, based on tests/test-mbrtowc5.sh. * modules/mbsrtowcs-tests (Files): Add it. (Makefile.am): Test it. * doc/posix-functions/mbsrtowcs.texi: Mention the C locale behaviour bug. --- diff --git a/ChangeLog b/ChangeLog index fba5f444f6..2fe1679061 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2023-03-30 Bruno Haible + + mbsrtowcs: Fix behaviour in the C locale. + * m4/mbsrtowcs.m4 (gl_FUNC_MBSRTOWCS): Invoke gl_MBRTOWC_C_LOCALE. If + mbrtowc is buggy in the C locale, override also mbsrtowcs. + * modules/mbsrtowcs (Files): Add m4/mbrtowc.m4. + * tests/test-mbsrtowcs.c (main): Add a test of the C locale, based on + tests/test-mbrtowc.c. + * tests/test-mbsrtowcs5.sh: New file, based on tests/test-mbrtowc5.sh. + * modules/mbsrtowcs-tests (Files): Add it. + (Makefile.am): Test it. + * doc/posix-functions/mbsrtowcs.texi: Mention the C locale behaviour + bug. + 2023-03-30 Bruno Haible mbrlen: Add tests. diff --git a/doc/posix-functions/mbsrtowcs.texi b/doc/posix-functions/mbsrtowcs.texi index f27ec0f616..28c450ddfb 100644 --- a/doc/posix-functions/mbsrtowcs.texi +++ b/doc/posix-functions/mbsrtowcs.texi @@ -15,6 +15,10 @@ Minix 3.1.8, HP-UX 11.00, IRIX 6.5, mingw. This function does not work on some platforms: HP-UX 11, Solaris 11 2010-11. @item +In the C or POSIX locales, this function can return @code{(size_t) -1} +and set @code{errno} to @code{EILSEQ}: +glibc 2.35. +@item This function does not work when the first argument is NULL on some platforms: mingw. @end itemize diff --git a/m4/mbsrtowcs.m4 b/m4/mbsrtowcs.m4 index f95af621dd..4f2e88c5a0 100644 --- a/m4/mbsrtowcs.m4 +++ b/m4/mbsrtowcs.m4 @@ -1,4 +1,4 @@ -# mbsrtowcs.m4 serial 14 +# mbsrtowcs.m4 serial 15 dnl Copyright (C) 2008-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, @@ -32,6 +32,13 @@ AC_DEFUN([gl_FUNC_MBSRTOWCS], *yes) ;; *) REPLACE_MBSRTOWCS=1 ;; esac + if test $REPLACE_MBSRTOWCS = 0; then + gl_MBRTOWC_C_LOCALE + case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in + *yes) ;; + *) REPLACE_MBSRTOWCS=1 ;; + esac + fi fi fi ]) diff --git a/modules/mbsrtowcs b/modules/mbsrtowcs index 4b5fa61cf4..70e7d0c36f 100644 --- a/modules/mbsrtowcs +++ b/modules/mbsrtowcs @@ -7,6 +7,7 @@ lib/mbsrtowcs-impl.h lib/mbsrtowcs-state.c m4/mbsrtowcs.m4 m4/mbstate_t.m4 +m4/mbrtowc.m4 m4/locale-fr.m4 m4/locale-ja.m4 m4/locale-zh.m4 diff --git a/modules/mbsrtowcs-tests b/modules/mbsrtowcs-tests index d7301057d9..36050c670d 100644 --- a/modules/mbsrtowcs-tests +++ b/modules/mbsrtowcs-tests @@ -3,6 +3,7 @@ tests/test-mbsrtowcs1.sh tests/test-mbsrtowcs2.sh tests/test-mbsrtowcs3.sh tests/test-mbsrtowcs4.sh +tests/test-mbsrtowcs5.sh tests/test-mbsrtowcs.c tests/signature.h tests/macros.h @@ -24,7 +25,9 @@ gt_LOCALE_JA gt_LOCALE_ZH_CN Makefile.am: -TESTS += test-mbsrtowcs1.sh test-mbsrtowcs2.sh test-mbsrtowcs3.sh test-mbsrtowcs4.sh +TESTS += \ + test-mbsrtowcs1.sh test-mbsrtowcs2.sh test-mbsrtowcs3.sh test-mbsrtowcs4.sh \ + test-mbsrtowcs5.sh TESTS_ENVIRONMENT += \ LOCALE_FR='@LOCALE_FR@' \ LOCALE_FR_UTF8='@LOCALE_FR_UTF8@' \ diff --git a/tests/test-mbsrtowcs.c b/tests/test-mbsrtowcs.c index d511690db9..7e8cc4a1ea 100644 --- a/tests/test-mbsrtowcs.c +++ b/tests/test-mbsrtowcs.c @@ -281,6 +281,72 @@ main (int argc, char *argv[]) } break; + case '5': + /* C or POSIX locale. */ + { + char input[] = "n/a"; + memset (&state, '\0', sizeof (mbstate_t)); + + src = input; + temp_state = state; + ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 1, &temp_state); + ASSERT (ret == 3); + ASSERT (src == input); + ASSERT (mbsinit (&state)); + + src = input; + ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 1, &state); + ASSERT (ret == (unlimited ? 3 : 1)); + ASSERT (src == (unlimited ? NULL : input + 1)); + ASSERT (buf[0] == 'n'); + if (unlimited) + { + ASSERT (buf[1] == '/'); + ASSERT (buf[2] == 'a'); + ASSERT (buf[3] == 0); + ASSERT (buf[4] == (wchar_t) 0xBADFACE); + } + else + ASSERT (buf[1] == (wchar_t) 0xBADFACE); + ASSERT (mbsinit (&state)); + } + { + int c; + char input[2]; + + memset (&state, '\0', sizeof (mbstate_t)); + for (c = 0; c < 0x100; c++) + if (c != 0) + { + /* We are testing all nonnull bytes. */ + input[0] = c; + input[1] = '\0'; + + src = input; + ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 1, &state); + ASSERT (ret == 1); + ASSERT (src == input); + ASSERT (mbsinit (&state)); + + buf[0] = buf[1] = (wchar_t) 0xBADFACE; + src = input; + ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 1, &state); + /* POSIX:2018 says: "In the POSIX locale an [EILSEQ] error + cannot occur since all byte values are valid characters." */ + ASSERT (ret == 1); + ASSERT (src == (unlimited ? NULL : input + 1)); + if (c < 0x80) + /* c is an ASCII character. */ + ASSERT (buf[0] == c); + else + /* On most platforms, the bytes 0x80..0xFF map to U+0080..U+00FF. + But on musl libc, the bytes 0x80..0xFF map to U+DF80..U+DFFF. */ + ASSERT (buf[0] == (btowc (c) == 0xDF00 + c ? btowc (c) : c)); + ASSERT (mbsinit (&state)); + } + } + break; + default: return 1; } diff --git a/tests/test-mbsrtowcs5.sh b/tests/test-mbsrtowcs5.sh new file mode 100755 index 0000000000..96734a73bd --- /dev/null +++ b/tests/test-mbsrtowcs5.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Test whether the POSIX locale has encoding errors. +LC_ALL=C \ +${CHECKER} ./test-mbsrtowcs${EXEEXT} 5 || exit 1 +LC_ALL=POSIX \ +${CHECKER} ./test-mbsrtowcs${EXEEXT} 5 || exit 1 + +exit 0