[Bug 272218] mbsinit returns true for a state that is not in the initial state
Date: Mon, 26 Jun 2023 07:34:43 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=272218 Bug ID: 272218 Summary: mbsinit returns true for a state that is not in the initial state Product: Base System Version: 13.2-RELEASE Hardware: Any OS: Any Status: New Severity: Affects Some People Priority: --- Component: standards Assignee: standards@FreeBSD.org Reporter: bruno@clisp.org Attachment #243004 text/plain mime type: Created attachment 243004 --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=243004&action=edit test case foo.c The following program makes 3 calls to the mbrtoc16 function and each time prints the results, including whether the mbstate_t in then in the initial state or not. Then it makes a second round, clearing the mbstate_t after the first call. ================================= foo.c ================================= #include <stdio.h> #include <string.h> #include <uchar.h> #include <wchar.h> int main () { if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) return 1; for (int round = 1; round <= 2; round++) { printf ("=== Round %d ===\n", round); mbstate_t state = { 0 }; char input[4] = { (char) 0xF0, (char) 0x9F, (char) 0x99, (char) 0x82 }; /* U+1F642 */ char16_t wc = (char16_t) 0xDEADBEEF; int ret = mbrtoc16 (&wc, input, 4, &state); printf ("ret = %d, wc = 0x%04X, back_to_initial=%d\n", ret, (unsigned int) wc, mbsinit(&state) != 0); if (round == 2) memset (&state, '\0', sizeof(state)); if (ret == 4) { wc = (char16_t) 0xDEADBEEF; ret = mbrtoc16 (&wc, input+4, 0, &state); printf ("ret = %d, wc = 0x%04X, back_to_initial=%d\n", ret, (unsigned int) wc, mbsinit(&state) != 0); if (ret == -2 || ret == -3) { wc = (char16_t) 0xDEADBEEF; ret = mbrtoc16 (&wc, "", 0, &state); printf ("ret = %d, wc = 0x%04X, back_to_initial=%d\n", ret, (unsigned int) wc, mbsinit(&state) != 0); } } } return 0; } /* Expected output (seen on glibc, musl libc): === Round 1 === ret = 4, wc = 0xD83D, back_to_initial=0 ret = -3, wc = 0xDE42, back_to_initial=1 ret = -2, wc = 0xBEEF, back_to_initial=1 === Round 2 === ret = 4, wc = 0xD83D, back_to_initial=0 ret = -2, wc = 0xBEEF, back_to_initial=1 ret = -2, wc = 0xBEEF, back_to_initial=1 */ ========================================================================= $ cc -Wall foo.c $ ./a.out === Round 1 === ret = 4, wc = 0xD83D, back_to_initial=1 ret = -3, wc = 0xDE42, back_to_initial=1 ret = -2, wc = 0xBEEF, back_to_initial=1 === Round 2 === ret = 4, wc = 0xD83D, back_to_initial=1 ret = -2, wc = 0xBEEF, back_to_initial=1 ret = -2, wc = 0xBEEF, back_to_initial=1 Since, after the first call, mbsinit() reports that the mbstate_t is in the initial state, it should make no difference if the program clears it (= forces it into the initial state) or not. But in FreeBSD 13.2, it makes a difference: The output of round 2 is different from the output of round 1. This proves that the mbstate_t was not in the initial state. That is, in the first line, mbsinit() should have returned zero instead of non-zero. Reference: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mbsinit.html -- You are receiving this mail because: You are the assignee for the bug.