+2023-03-30 Bruno Haible <bruno@clisp.org>
+
+ mbsnrtowcs: Fix behaviour in the C locale.
+ * m4/mbsnrtowcs.m4 (gl_FUNC_MBSNRTOWCS): Invoke gl_MBRTOWC_C_LOCALE. If
+ mbrtowc is buggy in the C locale, override also mbsnrtowcs.
+ * modules/mbsnrtowcs (Files): Add m4/mbrtowc.m4.
+ * tests/test-mbsnrtowcs.c (main): Add a test of the C locale, based on
+ tests/test-mbsrtowcs.c.
+ * tests/test-mbsnrtowcs5.sh: New file, based on tests/test-mbrtowc5.sh.
+ * modules/mbsnrtowcs-tests (Files): Add it.
+ (Makefile.am): Test it.
+ * doc/posix-functions/mbsnrtowcs.texi: Mention the C locale behaviour
+ bug.
+
2023-03-30 Bruno Haible <bruno@clisp.org>
mbsrtowcs: Fix behaviour in the C locale.
@item
This function produces invalid wide characters on some platforms:
Solaris 11.4.
+@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.
@end itemize
Portability problems not fixed by Gnulib:
-# mbsnrtowcs.m4 serial 8
+# mbsnrtowcs.m4 serial 9
dnl Copyright (C) 2008, 2010-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,
*yes) ;;
*) REPLACE_MBSNRTOWCS=1 ;;
esac
+ if test $REPLACE_MBSNRTOWCS = 0; then
+ gl_MBRTOWC_C_LOCALE
+ case "$gl_cv_func_mbrtowc_C_locale_sans_EILSEQ" in
+ *yes) ;;
+ *) REPLACE_MBSNRTOWCS=1 ;;
+ esac
+ fi
fi
fi
])
lib/mbsrtowcs-state.c
m4/mbsnrtowcs.m4
m4/mbstate_t.m4
+m4/mbrtowc.m4
Depends-on:
wchar
tests/test-mbsnrtowcs2.sh
tests/test-mbsnrtowcs3.sh
tests/test-mbsnrtowcs4.sh
+tests/test-mbsnrtowcs5.sh
tests/test-mbsnrtowcs.c
tests/signature.h
tests/macros.h
gt_LOCALE_ZH_CN
Makefile.am:
-TESTS += test-mbsnrtowcs1.sh test-mbsnrtowcs2.sh test-mbsnrtowcs3.sh test-mbsnrtowcs4.sh
+TESTS += \
+ test-mbsnrtowcs1.sh test-mbsnrtowcs2.sh test-mbsnrtowcs3.sh \
+ test-mbsnrtowcs4.sh test-mbsnrtowcs5.sh
TESTS_ENVIRONMENT += \
LOCALE_FR='@LOCALE_FR@' \
LOCALE_FR_UTF8='@LOCALE_FR_UTF8@' \
}
break;
+ case '5':
+ /* C or POSIX locale. */
+ {
+ char input[] = "n/a";
+ memset (&state, '\0', sizeof (mbstate_t));
+
+ src = input;
+ temp_state = state;
+ ret = mbsnrtowcs (NULL, &src, 4, unlimited ? BUFSIZE : 1, &temp_state);
+ ASSERT (ret == 3);
+ ASSERT (src == input);
+ ASSERT (mbsinit (&state));
+
+ src = input;
+ ret = mbsnrtowcs (buf, &src, 4, 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 = mbsnrtowcs (NULL, &src, 2, unlimited ? BUFSIZE : 1, &state);
+ ASSERT (ret == 1);
+ ASSERT (src == input);
+ ASSERT (mbsinit (&state));
+
+ buf[0] = buf[1] = (wchar_t) 0xBADFACE;
+ src = input;
+ ret = mbsnrtowcs (buf, &src, 2, 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;
}
--- /dev/null
+#!/bin/sh
+
+# Test whether the POSIX locale has encoding errors.
+LC_ALL=C \
+${CHECKER} ./test-mbsnrtowcs${EXEEXT} 5 || exit 1
+LC_ALL=POSIX \
+${CHECKER} ./test-mbsnrtowcs${EXEEXT} 5 || exit 1
+
+exit 0