From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16085 invoked by alias); 27 Feb 2003 10:36:01 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 16063 invoked by uid 71); 27 Feb 2003 10:36:01 -0000 Resent-Date: 27 Feb 2003 10:36:01 -0000 Resent-Message-ID: <20030227103601.16062.qmail@sources.redhat.com> Resent-From: gcc-gnats@gcc.gnu.org (GNATS Filer) Resent-Cc: gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org Resent-Reply-To: gcc-gnats@gcc.gnu.org, peturr02@ru.is Received: (qmail 13479 invoked by uid 48); 27 Feb 2003 10:27:18 -0000 Message-Id: <20030227102718.13478.qmail@sources.redhat.com> Date: Thu, 27 Feb 2003 10:36:00 -0000 From: peturr02@ru.is Reply-To: peturr02@ru.is To: gcc-gnats@gcc.gnu.org X-Send-Pr-Version: gnatsweb-2.9.3 (1.1.1.1.2.31) Subject: libstdc++/9875: filebuf doesn't handle codecvt::encoding() > 1 X-SW-Source: 2003-02/txt/msg01410.txt.bz2 List-Id: >Number: 9875 >Category: libstdc++ >Synopsis: filebuf doesn't handle codecvt::encoding() > 1 >Confidential: no >Severity: serious >Priority: medium >Responsible: unassigned >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Thu Feb 27 10:36:01 UTC 2003 >Closed-Date: >Last-Modified: >Originator: peturr02@ru.is >Release: gcc-3.2.1 >Organization: >Environment: Red Hat Linux 8.0 >Description: Many basic_filebuf members (at least seekoff, seekpos, sync, overflow, underflow) can't handle fixed width multibyte encodings (where codecvt<>::encoding() > 1). It seems that every place _M_file.seekoff is called, it is assumed that codecvt<>::encoding() == 1. >How-To-Repeat: See attachment. Note that this test is incomplete because the bug in seekoff shadows some of the other bugs. >Fix: >Release-Note: >Audit-Trail: >Unformatted: ----gnatsweb-attachment---- Content-Type: text/plain; name="seekoffbug.cc" Content-Disposition: inline; filename="seekoffbug.cc" #include #include #include #include #undef NDEBUG #include class Cvt : public std::codecvt { protected: virtual std::codecvt_base::result do_out(std::mbstate_t&, const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, char* to, char* to_end, char*& to_next) const { std::size_t from_len = from_end - from; std::size_t to_len = (to_end - to) / sizeof(wchar_t); std::size_t len = std::min(from_len, to_len); std::memcpy(to, from, len * sizeof(wchar_t)); from_next = from + len; to_next = to + len * sizeof(wchar_t); return from_next == from_end ? std::codecvt_base::ok : std::codecvt_base::partial; } virtual std::codecvt_base::result do_in(std::mbstate_t&, const char* from, const char* from_end, const char*& from_next, wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const { std::size_t from_len = (from_end - from) / sizeof(wchar_t); std::size_t to_len = to_end - to; std::size_t len = std::min(from_len, to_len); std::memcpy(to, from, len * sizeof(wchar_t)); from_next = from + len * sizeof(wchar_t); to_next = to + len; return from_next == from_end ? std::codecvt_base::ok : std::codecvt_base::partial; } virtual std::codecvt_base::result do_unshift(std::mbstate_t&, char*, char*, char*&) const { return std::codecvt_base::noconv; } virtual int do_encoding() const throw() { return sizeof(wchar_t); } virtual bool do_always_noconv() const throw() { return false; } virtual int do_length(std::mbstate_t&, const char* from, const char* end, std::size_t max) { std::size_t len = (end - from) / sizeof(wchar_t); return std::min(len, max) * sizeof(wchar_t); } virtual int do_max_length() const throw() { return sizeof(wchar_t); } }; void test1() { using namespace std; // seekoff wfilebuf fb; fb.pubimbue(locale(locale::classic(), new Cvt)); fb.open("tmp", ios_base::out | ios_base::in | ios_base::trunc); fb.sputn(L"0123456789", 10); fb.pubseekoff(-3, ios_base::cur); assert(fb.sgetc() == L'7'); fb.pubseekoff(-3, ios_base::cur); assert(fb.sgetc() == L'4'); fb.close(); } void test2() { using namespace std; // seekpos wfilebuf fb; fb.pubimbue(locale(locale::classic(), new Cvt)); fb.open("tmp", ios_base::out | ios_base::in | ios_base::trunc); fb.sputn(L"0123456789", 10); streampos p1 = fb.pubseekoff(0, ios_base::cur); assert(p1 != streampos(-1)); fb.sputc(L'a'); streampos p2 = fb.pubseekpos(p1); assert(p2 != streampos(-1)); assert(p2 == p1); assert(fb.sgetc() == L'a'); fb.pubseekoff(0, ios_base::beg); wchar_t buf[11]; streamsize s1 = fb.sgetn(buf, 11); assert(s1 == 11); assert(!wmemcmp(buf, L"0123456789a", 11)); fb.close(); } void test3() { using namespace std; // overflow locale loc (locale::classic(), new Cvt); wfilebuf fb1; fb1.pubimbue(loc); fb1.open("tmp", ios_base::out | ios_base::trunc); fb1.sputn(L"0123456789", 10); fb1.close(); wfilebuf fb2; fb2.pubimbue(loc); fb2.open("tmp", ios_base::in | ios_base::out); fb2.sputc(L'a'); fb2.close(); wfilebuf fb3; fb3.pubimbue(loc); fb3.open("tmp", ios_base::in); assert(fb3.is_open()); wchar_t buf[10]; streamsize s1 = fb3.sgetn(buf, 10); assert(s1 == 10); assert(!wmemcmp(buf, L"a123456789", 10)); fb3.close(); } int main() { test1(); test2(); test3(); return 0; }