[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.