[Bug 272218] mbsinit returns true for a state that is not in the initial state

[email protected]
Newsgroups gmane.os.freebsd.devel.standards
Message-ID <[email protected]/bugzilla/>
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: [email protected]
          Reporter: [email protected]
 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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.