> Failures on Cygwin 1.7.2
> ------------------------
>
> test-mbsnrtowcs.c:181: assertion failed
> ./test-mbsnrtowcs2.sh: line 15: 5708 Aborted (core dumped)
> LC_ALL=$LOCALE_FR_UTF8 ./test-mbsnrtowcs${EXEEXT} 2
> FAIL: test-mbsnrtowcs2.sh
>
> test-mbsrtowcs.c:181: assertion failed
> ./test-mbsrtowcs2.sh: line 15: 4428 Aborted (core dumped)
> LC_ALL=$LOCALE_FR_UTF8 ./test-mbsrtowcs${EXEEXT} 2
> FAIL: test-mbsrtowcs2.sh
These look like a programming error in the testcase or like a gcc bug.
A simplified test case is attached. It crashes when optimized with -O2
and works fine without optimization:
$ gcc foo.c && ./a.exe
gcc foo.c && ./a.exe
buf = FACE FACE FACE FACE FACE FACE FACE FACE FACE FACE
state = 0000000000000000
buf = FACE FACE FACE FACE FACE FACE FACE FACE FACE FACE
state = 01000000C3000000
buf = FACE FACE FACE FACE FACE FACE FACE FACE FACE FACE
state = 01000000C3000000
temps = 00000000C3000000
buf = 00FC 00DF FACE FACE FACE FACE FACE FACE FACE FACE
state = 00000000C3000000
$ gcc -O2 foo.c && ./a.exe
gcc -O2 foo.c && ./a.exe
buf = FACE FACE FACE FACE FACE FACE FACE FACE FACE FACE
state = 0000000000000000
buf = FACE FACE FACE FACE FACE FACE FACE FACE FACE FACE
state = 01000000C3000000
buf = FACE FACE FACE FACE FACE FACE FACE FACE FACE FACE
state = 01000000C3000000
temps = 00000000C3000000
buf = 00FC 00DF FACE FACE FACE FACE FACE FACE FACE FACE
state = 6100000000D4CD22
foo.c:103: assertion failed
bash: [5936: 1] tcsetattr: Inappropriate ioctl for device
Aborted (core dumped)
The same behaviour also occurs when the test case uses the gnulib replacement
of mbsrtowcs. Therefore I think it's not a bug in Cygwin's mbsrtowcs function.
Can someone please look at the attached test case and see if it does something
obviously wrong?
Bruno
#include <wchar.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ASSERT(expr) \
do \
{ \
if (!(expr)) \
{ \
fprintf (stderr, "%s:%d: assertion failed\n", \
__FILE__, __LINE__); \
fflush (stderr); \
abort (); \
} \
} \
while (0)
#define BUFSIZE 10
static void dumpbuf(wchar_t buf[BUFSIZE])
{
int i;
printf ("buf =");
for (i = 0; i < BUFSIZE; i++)
printf(" %04X", buf[i]);
printf ("\n");
fflush (stdout);
}
static void dumpstate(const char *prefix, mbstate_t *statep)
{
int i;
printf ("%s = ", prefix);
for (i = 0; i < sizeof (mbstate_t); i++)
printf("%02X", ((unsigned char *)statep)[i]);
printf ("\n");
fflush (stdout);
}
int
main (int argc, char *argv[])
{
int unlimited;
mbstate_t state;
wchar_t wc;
size_t ret;
if (setlocale (LC_ALL, "fr_FR.UTF-8") == NULL)
return 1;
for (unlimited = 0; unlimited < 1; unlimited++)
{
wchar_t buf[BUFSIZE];
const char *src;
mbstate_t temp_state;
{
size_t i;
for (i = 0; i < BUFSIZE; i++)
buf[i] = (wchar_t) 0xBADFACE;
}
/* Locale encoding is UTF-8. */
{
char input[] = "B\303\274\303\237er";
memset (&state, '\0', sizeof (mbstate_t));
dumpbuf(buf); dumpstate("state",&state);
wc = (wchar_t) 0xBADFACE;
ret = mbrtowc (&wc, input + 1, 1, &state);
ASSERT (ret == (size_t)(-2));
ASSERT (wc == (wchar_t) 0xBADFACE);
ASSERT (!mbsinit (&state));
input[1] = '\0';
dumpbuf(buf); dumpstate("state",&state);
src = input + 2;
temp_state = state;
ret = mbsrtowcs (NULL, &src, unlimited ? BUFSIZE : 2, &temp_state);
ASSERT (ret == 4);
ASSERT (src == input + 2);
ASSERT (!mbsinit (&state));
dumpbuf(buf); dumpstate("state",&state); dumpstate("temps",&temp_state);
src = input + 2;
ret = mbsrtowcs (buf, &src, unlimited ? BUFSIZE : 2, &state);
ASSERT (ret == (unlimited ? 4 : 2));
ASSERT (src == (unlimited ? NULL : input + 5));
ASSERT (wctob (buf[0]) == EOF);
ASSERT (wctob (buf[1]) == EOF);
dumpbuf(buf); dumpstate("state",&state);
if (unlimited)
{
ASSERT (buf[2] == 'e');
ASSERT (buf[3] == 'r');
ASSERT (buf[4] == 0);
ASSERT (buf[5] == (wchar_t) 0xBADFACE);
}
else
ASSERT (buf[2] == (wchar_t) 0xBADFACE);
ASSERT (mbsinit (&state));
}
}
return 0;
}