From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28721 invoked by alias); 8 Jan 2003 11:06:02 -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 28700 invoked by uid 71); 8 Jan 2003 11:06:01 -0000 Resent-Date: 8 Jan 2003 11:06:01 -0000 Resent-Message-ID: <20030108110601.28699.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 28492 invoked by uid 61); 8 Jan 2003 11:03:30 -0000 Message-Id: <20030108110330.28491.qmail@sources.redhat.com> Date: Wed, 08 Jan 2003 11:06: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++/9224: Incorrect type of first parameter and incorrect return value of codecvt<>::length (DR75,DR305) X-SW-Source: 2003-01/txt/msg00531.txt.bz2 List-Id: >Number: 9224 >Category: libstdc++ >Synopsis: Incorrect type of first parameter and incorrect return value of codecvt<>::length (DR75,DR305) >Confidential: no >Severity: serious >Priority: medium >Responsible: unassigned >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Wed Jan 08 03:06:00 PST 2003 >Closed-Date: >Last-Modified: >Originator: peturr02@ru.is >Release: gcc-3.2.1 >Organization: >Environment: Red Hat Linux 8.0 >Description: 1. According to the resolution of Library Defect Report 75 < http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-defects.html#75 > the type of the first parameter of codecvt<>::length and do_length should be StateT&, not const StateT&. 2. DR75 also sets a requirement that the effect of length upon state be "as if" do_in were called. This does not seem to hold for codecvt or codecvt. 3. The rationale for DR302 makes it clear that when do_length is called with an invalid input sequence, it should return the number of elements that could be successfully converted. The current implementation of do_length makes no attempt to check if the input is valid. 4. DR305 leaves codecvt mostly implementation defined, but that definition appears to be missing (except for some vague talk about wcsrtombs). I can't find anything on what do_in does to state or what it considers invalid input, so it is not possible to test 2 or 3. >How-To-Repeat: This should test for item 1: class MyCvt : public codecvt { public: bool called; MyCvt() : called(false) { } int do_length(mbstate_t&, const char*, const char*, size_t) { called = true; return 0; } }; const char* p = NULL; mbstate_t s; MyCvt mc; mc.length(s, p, p, 0); assert(mc.called); >Fix: See attachment. The additional requirement that the effect on state be "as if" do_in were called is achieved by calling do_in. This is not neccessary for codecvt as DR19 clearly states that do_in shall not modify state if it returns noconv. The return value of codecvt::do_length is also modified to reflect DR305 and the rationale for DR302. This depends on do_in always setting from_next correctly, regardless of return value (see DR382). This seems not to be the case, but that is also a problem when calling do_in directly and is a separate issue. Patch is against gcc-20021230, but also applies to gcc-3.2.1. Tested on Red Hat Linux 8.0 on x86. >Release-Note: >Audit-Trail: >Unformatted: ----gnatsweb-attachment---- Content-Type: text/plain; name="dr75.patch" Content-Disposition: inline; filename="dr75.patch" diff -c3pr /home/petur/src/gcc-20021230/libstdc++-v3/config/locale/ieee_1003.1-2001/codecvt_specializations.h gcc-20021230/libstdc++-v3/config/locale/ieee_1003.1-2001/codecvt_specializations.h *** /home/petur/src/gcc-20021230/libstdc++-v3/config/locale/ieee_1003.1-2001/codecvt_specializations.h 2002-05-26 14:35:04.000000000 +0000 --- gcc-20021230/libstdc++-v3/config/locale/ieee_1003.1-2001/codecvt_specializations.h 2003-01-07 20:11:28.000000000 +0000 *************** *** 230,236 **** do_always_noconv() const throw(); virtual int ! do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int --- 230,236 ---- do_always_noconv() const throw(); virtual int ! do_length(state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int *************** *** 447,455 **** template int codecvt<_InternT, _ExternT, __enc_traits>:: ! do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const ! { return min(__max, static_cast(__end - __from)); } #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 74. Garbled text for codecvt::do_max_length --- 447,463 ---- template int codecvt<_InternT, _ExternT, __enc_traits>:: ! do_length(state_type& __state, const extern_type* __from, const extern_type* __end, size_t __max) const ! { ! size_t __blen = __max * sizeof(intern_type); ! intern_type* __buf = ! reinterpret_cast(__builtin_alloca(__blen)); ! const extern_type* __from_next; ! this->in(__state, __from, __end, __from_next, ! __buf, __buf + __max, __buf); ! return __from_next - __from; ! } #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 74. Garbled text for codecvt::do_max_length diff -c3pr /home/petur/src/gcc-20021230/libstdc++-v3/include/bits/codecvt.h gcc-20021230/libstdc++-v3/include/bits/codecvt.h *** /home/petur/src/gcc-20021230/libstdc++-v3/include/bits/codecvt.h 2002-09-11 03:36:45.000000000 +0000 --- gcc-20021230/libstdc++-v3/include/bits/codecvt.h 2003-01-07 19:38:14.000000000 +0000 *************** *** 106,112 **** { return this->do_always_noconv(); } int ! length(const state_type& __state, const extern_type* __from, const extern_type* __end, size_t __max) const { return this->do_length(__state, __from, __end, __max); } --- 106,112 ---- { return this->do_always_noconv(); } int ! length(state_type& __state, const extern_type* __from, const extern_type* __end, size_t __max) const { return this->do_length(__state, __from, __end, __max); } *************** *** 144,150 **** do_always_noconv() const throw() = 0; virtual int ! do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const = 0; virtual int --- 144,150 ---- do_always_noconv() const throw() = 0; virtual int ! do_length(state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const = 0; virtual int *************** *** 204,210 **** do_always_noconv() const throw(); virtual int ! do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int --- 204,210 ---- do_always_noconv() const throw(); virtual int ! do_length(state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int *************** *** 264,270 **** do_always_noconv() const throw(); virtual int ! do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int --- 264,270 ---- do_always_noconv() const throw(); virtual int ! do_length(state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int *************** *** 324,330 **** bool do_always_noconv() const throw(); virtual ! int do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int --- 324,330 ---- bool do_always_noconv() const throw(); virtual ! int do_length(state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const; virtual int diff -c3pr /home/petur/src/gcc-20021230/libstdc++-v3/src/codecvt.cc gcc-20021230/libstdc++-v3/src/codecvt.cc *** /home/petur/src/gcc-20021230/libstdc++-v3/src/codecvt.cc 2002-10-08 23:32:23.000000000 +0000 --- gcc-20021230/libstdc++-v3/src/codecvt.cc 2003-01-07 20:11:30.000000000 +0000 *************** namespace std *** 106,112 **** int codecvt:: ! do_length (const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const { return min(__max, static_cast(__end - __from)); } --- 106,112 ---- int codecvt:: ! do_length (state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const { return min(__max, static_cast(__end - __from)); } *************** namespace std *** 152,160 **** int codecvt:: ! do_length(const state_type&, const extern_type* __from, const extern_type* __end, size_t __max) const ! { return min(__max, static_cast(__end - __from)); } int codecvt:: --- 152,168 ---- int codecvt:: ! do_length(state_type& __state, const extern_type* __from, const extern_type* __end, size_t __max) const ! { ! size_t __blen = __max * sizeof(intern_type); ! intern_type* __buf = ! reinterpret_cast(__builtin_alloca(__blen)); ! const extern_type* __from_next; ! this->in(__state, __from, __end, __from_next, ! __buf, __buf + __max, __buf); ! return __from_next - __from; ! } int codecvt::