This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

libstdc++/9224: Incorrect type of first parameter and incorrect return value of codecvt<>::length (DR75,DR305)


>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<wchar_t, char, mbstate_t> or codecvt<I, E, __enc_traits>.

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<wchar_t, char, mbstate_t> 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<char, char, mbstate_t>
{
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<char, char, mbstate_t> as DR19 clearly states that do_in shall not modify state if it returns noconv.

The return value of codecvt<wchar_t, char, mbstate_t>::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<typename _InternT, typename _ExternT>
      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<size_t>(__end - __from)); }
  
  #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
  // 74.  Garbled text for codecvt::do_max_length
--- 447,463 ----
    template<typename _InternT, typename _ExternT>
      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<intern_type*>(__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<char, char, mbstate_t>::
!   do_length (const state_type&, const extern_type* __from,
  	     const extern_type* __end, size_t __max) const
    { return min(__max, static_cast<size_t>(__end - __from)); }
    
--- 106,112 ----
    
    int 
    codecvt<char, char, mbstate_t>::
!   do_length (state_type&, const extern_type* __from,
  	     const extern_type* __end, size_t __max) const
    { return min(__max, static_cast<size_t>(__end - __from)); }
    
*************** namespace std 
*** 152,160 ****
    
    int 
    codecvt<wchar_t, char, mbstate_t>::
!   do_length(const state_type&, const extern_type* __from,
  	    const extern_type* __end, size_t __max) const
!   { return min(__max, static_cast<size_t>(__end - __from)); }
  
    int 
    codecvt<wchar_t, char, mbstate_t>::
--- 152,168 ----
    
    int 
    codecvt<wchar_t, char, mbstate_t>::
!   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<intern_type*>(__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<wchar_t, char, mbstate_t>::


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]