From ea31b613feba1c5f34ff2cf9f2c0bab3be4f8d2a Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 16 Jan 2003 02:27:47 +0000 Subject: [PATCH] Update. * iconv/gconv_simple.c (STORE_REST): Explicitly store the total expected size into state. (UNPACK_BYTES): Do the reverse. * wcsmbs/tst-mbrtowc.c (utf8_test_1): Add test for the bug. Reported by Al Viro . --- ChangeLog | 6 ++++++ iconv/gconv_simple.c | 44 +++++++++++++------------------------------- wcsmbs/tst-mbrtowc.c | 18 +++++++++++++++++- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9c8c51301..57e1c6584a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2003-01-15 Ulrich Drepper + * iconv/gconv_simple.c (STORE_REST): Explicitly store the total + expected size into state. + (UNPACK_BYTES): Do the reverse. + * wcsmbs/tst-mbrtowc.c (utf8_test_1): Add test for the bug. + Reported by Al Viro . + * stdio-common/Makefile (tests): Add bug14. * stdio-common/bug14.c: New file. diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c index 3937b95c92..124c8e7727 100644 --- a/iconv/gconv_simple.c +++ b/iconv/gconv_simple.c @@ -1,5 +1,5 @@ /* Simple transformations functions. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1997. @@ -1031,7 +1031,7 @@ ucs4le_internal_loop_single (struct __gconv_step *step, correct and that it requires a larger number of bytes than there \ are in the input buffer. */ \ wint_t ch = **inptrp; \ - size_t cnt; \ + size_t cnt, r; \ \ state->__count = inend - *inptrp; \ \ @@ -1069,16 +1069,19 @@ ucs4le_internal_loop_single (struct __gconv_step *step, } \ \ /* The first byte is already consumed. */ \ - --cnt; \ + r = cnt - 1; \ while (++(*inptrp) < inend) \ { \ ch <<= 6; \ ch |= **inptrp & 0x3f; \ - --cnt; \ + --r; \ } \ \ /* Shift for the so far missing bytes. */ \ - ch <<= cnt * 6; \ + ch <<= r * 6; \ + \ + /* Store the number of bytes expected for the entire sequence. */ \ + ch = ch << 3 | cnt; \ \ /* Store the value. */ \ state->__value.__wch = ch; \ @@ -1086,35 +1089,14 @@ ucs4le_internal_loop_single (struct __gconv_step *step, #define UNPACK_BYTES \ { \ + static const unsigned char inmask[5] = { 0xc0, 0xe0, 0xf0, 0xf8, 0xfc }; \ wint_t wch = state->__value.__wch; \ - size_t ntotal; \ + size_t ntotal = wch & 7; \ + wch >>= 3; \ + \ inlen = state->__count; \ \ - if (state->__value.__wch <= 0x7ff) \ - { \ - bytebuf[0] = 0xc0; \ - ntotal = 2; \ - } \ - else if (__builtin_expect (state->__value.__wch <= 0xffff, 1)) \ - { \ - bytebuf[0] = 0xe0; \ - ntotal = 3; \ - } \ - else if (__builtin_expect (state->__value.__wch < 0x1fffff, 1)) \ - { \ - bytebuf[0] = 0xf0; \ - ntotal = 4; \ - } \ - else if (__builtin_expect (state->__value.__wch < 0x3ffffff, 1)) \ - { \ - bytebuf[0] = 0xf8; \ - ntotal = 5; \ - } \ - else \ - { \ - bytebuf[0] = 0xfc; \ - ntotal = 6; \ - } \ + bytebuf[0] = inmask[ntotal - 2]; \ \ do \ { \ diff --git a/wcsmbs/tst-mbrtowc.c b/wcsmbs/tst-mbrtowc.c index 4f1d1e586d..2400d8369f 100644 --- a/wcsmbs/tst-mbrtowc.c +++ b/wcsmbs/tst-mbrtowc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2000. @@ -17,6 +17,8 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +/* We always want assert to be fully defined. */ +#undef NDEBUG #include #include #include @@ -45,6 +47,20 @@ utf8_test_1 (void) assert (mbrtowc (&wc, "", 1, &s) == 0); /* test final byte processing */ assert (wc == 0); /* test final byte decoding */ + /* The following test is by Al Viro . */ + const char str[] = "\xe0\xa0\x80"; + + wc = 42; /* arbitrary number */ + memset (&s, 0, sizeof (s)); /* get s into initial state */ + assert (mbrtowc (&wc, str, 1, &s) == -2); + assert (mbrtowc (&wc, str + 1, 2, &s) == 2); + assert (wc == 0x800); + + wc = 42; /* arbitrary number */ + memset (&s, 0, sizeof (s)); /* get s into initial state */ + assert (mbrtowc (&wc, str, 3, &s) == 3); + assert (wc == 0x800); + return 0; }