NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

lib/47602: getwc() modifies input instead of returning EILSEQ.



>Number:         47602
>Category:       lib
>Synopsis:       getwc() modifies input instead of returning EILSEQ.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Feb 28 21:20:00 +0000 2013
>Originator:     Christos Zoulas
>Release:        NetBSD 5.99.59
>Organization:
        Entropy Busters LLC.
>Environment:
System: NetBSD rebar.astron.com 5.99.59 NetBSD 5.99.59 (GENERIC) #7: Fri Dec 30 
15:19:49 EST 2011 
christos%rebar.astron.com@localhost:/usr/src/sys/arch/amd64/compile/GENERIC 
amd64
Architecture: x86_64
Machine: amd64
>Description:

getwc() should not modify what it reads in order to make it compliant with
the charset it is supposed to be using. It should return an error instead.
Thanks to J.R. Oldroyd for submitting both the test program and the patch.

>How-To-Repeat:

#include <stdio.h>
#include <wchar.h>
#include <errno.h>
#include <locale.h>

main() {
        char *fname = ",getwc-test";
        wchar_t obuf[16];
        wint_t c, c1;
        FILE *fp;
        char *locales[] = {
                "C",
                "en_US.UTF-8",
                "ja_JP.eucJP",
                0,
        }, **locale;
        int i;
        
        obuf[0] = 0xa440;
        obuf[1] = 0xac4f;
        obuf[2] = 0xb36f;
        obuf[3] = 0xcf40;
        obuf[4] = L'\0';

        setlocale(LC_CTYPE, "zh_TW.Big5");
        fp = fopen(fname, "w");
        i = fwprintf(fp, L"%ls\n", obuf);
        fclose(fp);

        for (locale = locales; *locale; locale++) {
                setlocale(LC_CTYPE, *locale);
                fp = fopen(fname, "r");
                for (i = 0; i < wcslen(obuf); i++) {
                        c = getwc(fp);
                        if (c == WEOF && errno == EILSEQ)
                                c = (wint_t) getc(fp);
                        if ((c & 0xff00) == 0) {
                                c1 = getc(fp);
                                c = (c << 8) | c1;
                        }
                        if (c == obuf[i])
                                wprintf(L"%-12.12s %d wrote 0x%x read 0x%x 
ok\n", *locale, i, obuf[i], c);
                        else
                                wprintf(L"%-12.12s %d wrote 0x%x read 0x%x 
getwc error\n", *locale, i, obuf[i], c);
                }
                fclose(fp);
        }

        unlink(fname);
}

>Fix:

--- lib/libc/citrus/modules/citrus_euc.c.orig   2013-02-28 15:50:49.000000000 
-0500
+++ lib/libc/citrus/modules/citrus_euc.c        2013-02-28 15:53:59.000000000 
-0500
@@ -271,7 +271,8 @@
      wchar = 0;
      while (len-- > 0)
              wchar = (wchar << 8) | (*s1++ & 0xff);
-     wchar = (wchar & ~ei->mask) | ei->bits[cs];
+     if (wchar != (wchar & ~ei->mask) | ei->bits[cs])
+             goto encoding_error;

      psenc->chlen = 0;
      if (pwc)



Home | Main Index | Thread Index | Old Index