This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


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

Re: libstdc++/3720 is a 2.95 regression [PATCH]



A core dump caused by a buffer overflow in num_get::_M_extract(). This
affects all arithmetic input, making it impossible to write a robust
program that accepts numerical input without writing ones own number
parsing code. The simple program

  #include <iostream>
  int main()
  {
     int i;
     std::cin >> i;
  }

will cause a buffer overflow if the input stream contains more than 31
non-zero digits.

The following patch against the 3.0 branch replaces the fixed size
char array, with a std::vector<char>.

Philip



Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/ChangeLog,v
retrieving revision 1.452.2.155
diff -c -3 -p -r1.452.2.155 ChangeLog
*** ChangeLog	2001/08/19 21:08:35	1.452.2.155
--- ChangeLog	2001/08/24 15:02:36
***************
*** 1,3 ****
--- 1,12 ----
+ 2001-08-24  Philip Martin  <philip_martin@ntlworld.com>
+ 
+ 	libstdc++/3720
+ 	* include/bits/locale_facets.h: Replace char array with vector
+ 	* include/bits/locale_facets.tcc: Likewise
+ 	* src/locale.cc: Likewise
+ 	* src/locale-inst.cc: Add vector::_M_insert_aux explict instantiation
+ 	* testsuite/27_io/istream_extractor_arith.cc: Add test12 for excess input
+ 
  2001-08-19  Release Manager
  
  	* GCC 3.0.1 Released.
Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.12.2.2
diff -c -3 -p -r1.12.2.2 locale_facets.h
*** locale_facets.h	2001/06/04 19:30:55	1.12.2.2
--- locale_facets.h	2001/08/24 15:02:37
***************
*** 40,45 ****
--- 40,46 ----
  
  #include <bits/std_ctime.h>	// For struct tm
  #include <bits/std_ios.h>	// For ios_base
+ #include <bits/std_vector.h>	// For vector
  #ifdef _GLIBCPP_USE_WCHAR_T
  # include <langinfo.h>		// For codecvt
  # include <bits/std_cwctype.h>	// For wctype_t
*************** namespace std
*** 655,661 ****
        // NB: This is specialized for char.
        void 
        _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 
! 		 ios_base::iostate& __err, char* __xtrc, 
  		 int& __base, bool __fp = true) const;
  
        virtual iter_type 
--- 656,662 ----
        // NB: This is specialized for char.
        void 
        _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 
! 		 ios_base::iostate& __err, vector<char>& __xtrc, 
  		 int& __base, bool __fp = true) const;
  
        virtual iter_type 
*************** namespace std
*** 714,720 ****
      num_get<char, istreambuf_iterator<char> >::    
      _M_extract(istreambuf_iterator<char> __beg, 
  	       istreambuf_iterator<char> __end, ios_base& __io, 
! 	       ios_base::iostate& __err, char* __xtrc, 
  	       int& __base, bool __fp) const;
  
    // _Numeric_put is used by num_put, money_put, and time_put
--- 715,721 ----
      num_get<char, istreambuf_iterator<char> >::    
      _M_extract(istreambuf_iterator<char> __beg, 
  	       istreambuf_iterator<char> __end, ios_base& __io, 
! 	       ios_base::iostate& __err, vector<char>& __xtrc, 
  	       int& __base, bool __fp) const;
  
    // _Numeric_put is used by num_put, money_put, and time_put
Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.8.2.4
diff -c -3 -p -r1.8.2.4 locale_facets.tcc
*** locale_facets.tcc	2001/06/10 23:41:55	1.8.2.4
--- locale_facets.tcc	2001/08/24 15:02:38
*************** namespace std
*** 233,239 ****
    // strto[l,ll,f,d]. The thought was to encapsulate the conversion
    // into this one function, and thus the num_get::do_get member
    // functions can just adjust for the type of the overloaded
!   // argument and process the char array returned from _M_extract.
    // Other things were also considered, including a fused
    // multiply-add loop that would obviate the need for any call to
    // strto... at all: however, it would b e a bit of a pain, because
--- 233,239 ----
    // strto[l,ll,f,d]. The thought was to encapsulate the conversion
    // into this one function, and thus the num_get::do_get member
    // functions can just adjust for the type of the overloaded
!   // argument and process the vector of char produced by _M_extract.
    // Other things were also considered, including a fused
    // multiply-add loop that would obviate the need for any call to
    // strto... at all: however, it would b e a bit of a pain, because
*************** namespace std
*** 251,257 ****
      void
      num_get<_CharT, _InIter>::
      _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/,
!                ios_base::iostate& /*__err*/, char* /*__xtrc*/,
                 int& /*__base*/, bool /*__fp*/) const
      {
        // XXX Not currently done: need to expand upon char version below.
--- 251,257 ----
      void
      num_get<_CharT, _InIter>::
      _M_extract(_InIter /*__beg*/, _InIter /*__end*/, ios_base& /*__io*/,
!                ios_base::iostate& /*__err*/, vector<char>& /*__xtrc*/,
                 int& /*__base*/, bool /*__fp*/) const
      {
        // XXX Not currently done: need to expand upon char version below.
*************** namespace std
*** 262,268 ****
      num_get<char, istreambuf_iterator<char> >::
      _M_extract(istreambuf_iterator<char> __beg, 
  	       istreambuf_iterator<char> __end, ios_base& __io, 
! 	       ios_base::iostate& __err, char* __xtrc, int& __base, 
  	       bool __fp) const;
  
  #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
--- 262,268 ----
      num_get<char, istreambuf_iterator<char> >::
      _M_extract(istreambuf_iterator<char> __beg, 
  	       istreambuf_iterator<char> __end, ios_base& __io, 
! 	       ios_base::iostate& __err, vector<char>& __xtrc, int& __base, 
  	       bool __fp) const;
  
  #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
*************** namespace std
*** 282,298 ****
            // Stage 1: extract and determine the conversion specifier.
            // Assuming leading zeros eliminated, thus the size of 32 for
            // integral types.
!           char __xtrc[32] = {'\0'};
            int __base;
            _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
            // Stage 2: convert and store results.
            char* __sanity;
            errno = 0;
!           long __l = strtol(__xtrc, &__sanity, __base);
            if (!(__err & ios_base::failbit)
                && __l <= 1
!               && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
              __v = __l;
            else
              __err |= ios_base::failbit;
--- 282,299 ----
            // Stage 1: extract and determine the conversion specifier.
            // Assuming leading zeros eliminated, thus the size of 32 for
            // integral types.
!           vector<char> __xtrc;
!           __xtrc.reserve(32);
            int __base;
            _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
            // Stage 2: convert and store results.
            char* __sanity;
            errno = 0;
!           long __l = strtol(&__xtrc[0], &__sanity, __base);
            if (!(__err & ios_base::failbit)
                && __l <= 1
!               && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
              __v = __l;
            else
              __err |= ios_base::failbit;
*************** namespace std
*** 347,362 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long __l = strtol(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
            && __l >= SHRT_MIN && __l <= SHRT_MAX)
          __v = static_cast<short>(__l);
        else
--- 348,364 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long __l = strtol(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0
            && __l >= SHRT_MIN && __l <= SHRT_MAX)
          __v = static_cast<short>(__l);
        else
*************** namespace std
*** 374,389 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32] = {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long __l = strtol(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
            && __l >= INT_MIN && __l <= INT_MAX)
          __v = static_cast<int>(__l);
        else
--- 376,392 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long __l = strtol(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0
            && __l >= INT_MIN && __l <= INT_MAX)
          __v = static_cast<int>(__l);
        else
*************** namespace std
*** 402,417 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long __l = strtol(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __l;
        else
          __err |= ios_base::failbit;
--- 405,421 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long __l = strtol(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __l;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 429,444 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long long __ll = strtoll(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __ll;
        else
          __err |= ios_base::failbit;
--- 433,449 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long long __ll = strtoll(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __ll;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 456,471 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
            && __ul <= USHRT_MAX)
          __v = static_cast<unsigned short>(__ul);
        else
--- 461,477 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long __ul = strtoul(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0
            && __ul <= USHRT_MAX)
          __v = static_cast<unsigned short>(__ul);
        else
*************** namespace std
*** 483,498 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0
            && __ul <= UINT_MAX)
          __v = static_cast<unsigned int>(__ul);
        else
--- 489,505 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long __ul = strtoul(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0
            && __ul <= UINT_MAX)
          __v = static_cast<unsigned int>(__ul);
        else
*************** namespace std
*** 510,525 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32] = {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __ul;
        else
          __err |= ios_base::failbit;
--- 517,533 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long __ul = strtoul(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __ul;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 537,552 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __ull;
        else
          __err |= ios_base::failbit;
--- 545,561 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       unsigned long long __ull = strtoull(&__xtrc[0], &__sanity, __base);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __ull;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 564,570 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 256 for
        // floating-point types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
--- 573,580 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 256 for
        // floating-point types.
!       vector<char> __xtrc;
!       __xtrc.reserve(256);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
*************** namespace std
*** 572,583 ****
        char* __sanity;
        errno = 0;
  #ifdef _GLIBCPP_USE_C99
!       float __f = strtof(__xtrc, &__sanity);
  #else
!       float __f = static_cast<float>(strtod(__xtrc, &__sanity));
  #endif
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __f;
        else
          __err |= ios_base::failbit;
--- 582,593 ----
        char* __sanity;
        errno = 0;
  #ifdef _GLIBCPP_USE_C99
!       float __f = strtof(&__xtrc[0], &__sanity);
  #else
!       float __f = static_cast<float>(strtod(&__xtrc[0], &__sanity));
  #endif
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __f;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 594,609 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 256 for
        // floating-point types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       double __d = strtod(__xtrc, &__sanity);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __d;
        else
          __err |= ios_base::failbit;
--- 604,620 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 256 for
        // floating-point types.
!       vector<char> __xtrc;
!       __xtrc.reserve(256);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       double __d = strtod(&__xtrc[0], &__sanity);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __d;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 621,636 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 256 for
        // floating-point types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long double __ld = strtold(__xtrc, &__sanity);
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __ld;
        else
          __err |= ios_base::failbit;
--- 632,648 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 256 for
        // floating-point types.
!       vector<char> __xtrc;
!       __xtrc.reserve(256);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       long double __ld = strtold(&__xtrc[0], &__sanity);
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __ld;
        else
          __err |= ios_base::failbit;
*************** namespace std
*** 645,651 ****
             ios_base::iostate& __err, long double& __v) const
      {
        // Stage 1: extract
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
--- 657,664 ----
             ios_base::iostate& __err, long double& __v) const
      {
        // Stage 1: extract
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, true);
  
*************** namespace std
*** 663,669 ****
  
        // Stage 3: store results.
        long double __ld;
!       int __p = sscanf(__xtrc, __conv, &__ld);
        if (__p
            && static_cast<typename __traits_type::int_type>(__p)
          != __traits_type::eof())
--- 676,682 ----
  
        // Stage 3: store results.
        long double __ld;
!       int __p = sscanf(&__xtrc[0], __conv, &__ld);
        if (__p
            && static_cast<typename __traits_type::int_type>(__p)
          != __traits_type::eof())
*************** namespace std
*** 691,706 ****
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       char __xtrc[32]= {'\0'};
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
        if (!(__err & ios_base::failbit)
!           && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
          __v = __vp;
        else
          __err |= ios_base::failbit;
--- 704,721 ----
        // Stage 1: extract and determine the conversion specifier.
        // Assuming leading zeros eliminated, thus the size of 32 for
        // integral types.
!       vector<char> __xtrc;
!       __xtrc.reserve(32);
        int __base;
        _M_extract(__beg, __end, __io, __err, __xtrc, __base, false);
  
        // Stage 2: convert and store results.
        char* __sanity;
        errno = 0;
!       void* __vp = reinterpret_cast<void*>(strtoul(&__xtrc[0], &__sanity,
!                                            __base));
        if (!(__err & ios_base::failbit)
!           && __sanity != &__xtrc[0] && *__sanity == '\0' && errno == 0)
          __v = __vp;
        else
          __err |= ios_base::failbit;
Index: src/locale-inst.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/locale-inst.cc,v
retrieving revision 1.15.2.3
diff -c -3 -p -r1.15.2.3 locale-inst.cc
*** locale-inst.cc	2001/05/31 12:41:47	1.15.2.3
--- locale-inst.cc	2001/08/24 15:02:38
*************** namespace std
*** 319,323 ****
--- 319,330 ----
      fill(__normal_iterator<locale::facet**, vector<locale::facet*> >,
           __normal_iterator<locale::facet**, vector<locale::facet*> >,
           locale::facet* const&);
+ 
+   template
+     void
+     std::vector<char>::_M_insert_aux(
+       std::__normal_iterator<char*, std::vector<char, std::allocator<char> > >,
+       char const&);
+ 
  } // namespace std
  
Index: src/locale.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/locale.cc,v
retrieving revision 1.28.2.4
diff -c -3 -p -r1.28.2.4 locale.cc
*** locale.cc	2001/07/20 00:14:10	1.28.2.4
--- locale.cc	2001/08/24 15:02:39
*************** namespace std 
*** 651,664 ****
      num_get<char, istreambuf_iterator<char> >::
      _M_extract(istreambuf_iterator<char> __beg, 
  	       istreambuf_iterator<char> __end, ios_base& __io, 
! 	       ios_base::iostate& __err, char* __xtrc, int& __base, 
  	       bool __fp) const
      {
        typedef _Format_cache<char> __cache_type;	
  
-       // Prepare for possible failure
-       __xtrc[0] = '\0';
- 
        // Stage 1: determine a conversion specifier.
        ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
        if (__basefield == ios_base::dec)
--- 651,661 ----
      num_get<char, istreambuf_iterator<char> >::
      _M_extract(istreambuf_iterator<char> __beg, 
  	       istreambuf_iterator<char> __end, ios_base& __io, 
! 	       ios_base::iostate& __err, vector<char>& __xtrc, int& __base, 
  	       bool __fp) const
      {
        typedef _Format_cache<char> __cache_type;	
  
        // Stage 1: determine a conversion specifier.
        ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
        if (__basefield == ios_base::dec)
*************** namespace std 
*** 680,685 ****
--- 677,683 ----
        // Fail quickly if !__valid
        if (__beg == __end)
          {
+           __xtrc.push_back('\0');
            __err |= (ios_base::eofbit | ios_base::failbit);
            return;
          }
*************** namespace std 
*** 687,693 ****
        // Acceptable formats for numbers here are based on 22.2.3.1
        string __grp;
        int __sep_pos = 0;
-       int __pos = 0;
        const char* __lits = __fmt->_S_literals;
        char __c = *__beg;
  
--- 685,690 ----
*************** namespace std 
*** 697,703 ****
  	  || (__c == __lits[__cache_type::_S_plus]))
          {
            __testsign = true;
!           __xtrc[__pos++] = __c;
            ++__beg;
  	  __c = * __beg;
  
--- 694,700 ----
  	  || (__c == __lits[__cache_type::_S_plus]))
          {
            __testsign = true;
!           __xtrc.push_back(__c);
            ++__beg;
  	  __c = * __beg;
  
*************** namespace std 
*** 711,717 ****
            // There had better be more to come...
            if (__beg == __end)
              {
!               __xtrc[__pos] = '\0';
                __err |= (ios_base::eofbit | ios_base::failbit);
                return;
              }
--- 708,714 ----
            // There had better be more to come...
            if (__beg == __end)
              {
!               __xtrc.push_back('\0');
                __err |= (ios_base::eofbit | ios_base::failbit);
                return;
              }
*************** namespace std 
*** 729,736 ****
             // a plain '0' (possibly with a sign) can be got rid of now
             if (__beg == __end)
               {
!                __xtrc[__pos++] = __lits[__cache_type::_S_digits];
!                __xtrc[__pos] = '\0';
                 __err |= ios_base::eofbit;
                 return;
               }
--- 726,733 ----
             // a plain '0' (possibly with a sign) can be got rid of now
             if (__beg == __end)
               {
!                __xtrc.push_back(__lits[__cache_type::_S_digits]);
!                __xtrc.push_back('\0');
                 __err |= ios_base::eofbit;
                 return;
               }
*************** namespace std 
*** 784,790 ****
  		     && __p < &__lits[__cache_type::_S_udigits + __base])))
  	    {
  	      // Try first for acceptable digit; record it if found.
! 	      __xtrc[__pos++] = __c;
  	      ++__sep_pos;
  	      __testunits = true;
  	      ++__beg;
--- 781,787 ----
  		     && __p < &__lits[__cache_type::_S_udigits + __base])))
  	    {
  	      // Try first for acceptable digit; record it if found.
! 	      __xtrc.push_back(__c);
  	      ++__sep_pos;
  	      __testunits = true;
  	      ++__beg;
*************** namespace std 
*** 844,850 ****
            if (!__test)
              {
                __err |= ios_base::failbit;
!               __xtrc[__pos] = '\0';
                if (__beg == __end)
                  __err |= ios_base::eofbit;
                return;
--- 841,847 ----
            if (!__test)
              {
                __err |= ios_base::failbit;
!               __xtrc.push_back('\0');
                if (__beg == __end)
                  __err |= ios_base::eofbit;
                return;
*************** namespace std 
*** 852,859 ****
          }
  
        // If there was nothing but zeros, put one in the output string
!       if (__testzero && (__pos == 0 || (__pos == 1 && __testsign)))
!         __xtrc[__pos++] = __lits[__cache_type::_S_digits];
  
        // That's it for integer types. Remaining code is for floating point
        if (__fp && __beg != __end)
--- 849,857 ----
          }
  
        // If there was nothing but zeros, put one in the output string
!       if (__testzero && (__xtrc.size() == 0
!           || (__xtrc.size() == 1 && __testsign)))
!         __xtrc.push_back(__lits[__cache_type::_S_digits]);
  
        // That's it for integer types. Remaining code is for floating point
        if (__fp && __beg != __end)
*************** namespace std 
*** 864,870 ****
                                       // with digits following it?
            if (__c == __fmt->_M_decimal_point)
              {
!               __xtrc[__pos++] = '.';
                ++__beg;
  	      __c = *__beg;
  
--- 862,868 ----
                                       // with digits following it?
            if (__c == __fmt->_M_decimal_point)
              {
!               __xtrc.push_back('.');
                ++__beg;
  	      __c = *__beg;
  
*************** namespace std 
*** 878,884 ****
                         || (__p >= &__lits[__cache_type::_S_udigits]
                             && __p < &__lits[__cache_type::_S_udigits + __base]))
                      {
!                       __xtrc[__pos++] = __c;
                        ++__beg;
  		      __c = *__beg;
                        __testdec = true;
--- 876,882 ----
                         || (__p >= &__lits[__cache_type::_S_udigits]
                             && __p < &__lits[__cache_type::_S_udigits + __base]))
                      {
!                       __xtrc.push_back(__c);
                        ++__beg;
  		      __c = *__beg;
                        __testdec = true;
*************** namespace std 
*** 890,896 ****
            if (!__testunits && !__testdec) // Ill formed
              {
                __err |= ios_base::failbit;
!               __xtrc[__pos] = '\0';
                if (__beg == __end)
                  __err |= ios_base::eofbit;
                return;
--- 888,894 ----
            if (!__testunits && !__testdec) // Ill formed
              {
                __err |= ios_base::failbit;
!               __xtrc.push_back('\0');
                if (__beg == __end)
                  __err |= ios_base::eofbit;
                return;
*************** namespace std 
*** 902,908 ****
                if ((__c == __lits[__cache_type::_S_ee])
                     || (__c == __lits[__cache_type::_S_Ee]))
                  {
!                   __xtrc[__pos++] = __c;
                    ++__beg;
  		  __c = *__beg;
  
--- 900,906 ----
                if ((__c == __lits[__cache_type::_S_ee])
                     || (__c == __lits[__cache_type::_S_Ee]))
                  {
!                   __xtrc.push_back(__c);
                    ++__beg;
  		  __c = *__beg;
  
*************** namespace std 
*** 912,918 ****
                        if ((__c == __lits[__cache_type::_S_minus])
                            || (__c == __lits[__cache_type::_S_plus]))
                          {
!                           __xtrc[__pos++] = __c;
                            ++__beg;
  			  __c = *__beg;
                            // whitespace may follow a sign
--- 910,916 ----
                        if ((__c == __lits[__cache_type::_S_minus])
                            || (__c == __lits[__cache_type::_S_plus]))
                          {
!                           __xtrc.push_back(__c);
                            ++__beg;
  			  __c = *__beg;
                            // whitespace may follow a sign
*************** namespace std 
*** 926,932 ****
                    // And now there must be some digits
                    if (__beg == __end)
                      {
!                       __xtrc[__pos] = '\0';
                        __err |= (ios_base::eofbit | ios_base::failbit);
                        return;
                      }
--- 924,930 ----
                    // And now there must be some digits
                    if (__beg == __end)
                      {
!                       __xtrc.push_back('\0');
                        __err |= (ios_base::eofbit | ios_base::failbit);
                        return;
                      }
*************** namespace std 
*** 938,944 ****
                             || (__p >= &__lits[__cache_type::_S_udigits]
                                 && __p < &__lits[__cache_type::_S_udigits + __base]))
                          {
!                           __xtrc[__pos++] = __c;
                            ++__beg;
  			  __c = *__beg;
                          }
--- 936,942 ----
                             || (__p >= &__lits[__cache_type::_S_udigits]
                                 && __p < &__lits[__cache_type::_S_udigits + __base]))
                          {
!                           __xtrc.push_back(__c);
                            ++__beg;
  			  __c = *__beg;
                          }
*************** namespace std 
*** 951,957 ****
          }
  
        // Finish up
!       __xtrc[__pos] = '\0';
        if (__beg == __end)
          __err |= ios_base::eofbit;
      }
--- 949,955 ----
          }
  
        // Finish up
!       __xtrc.push_back('\0');
        if (__beg == __end)
          __err |= ios_base::eofbit;
      }
Index: testsuite/27_io/istream_extractor_arith.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/istream_extractor_arith.cc,v
retrieving revision 1.8.4.1
diff -c -3 -p -r1.8.4.1 istream_extractor_arith.cc
*** istream_extractor_arith.cc	2001/05/14 19:49:23	1.8.4.1
--- istream_extractor_arith.cc	2001/08/24 15:02:39
*************** bool test11()
*** 513,518 ****
--- 513,552 ----
    return test;
  }
  
+ // libstdc++/3720
+ // excess input should not cause a core dump
+ template<typename T>
+ bool test12_aux()
+ {
+   bool test = true;
+ 
+   // this many digits will overflow
+   int digits_overflow = std::numeric_limits<long double>::max_exponent10 + 1;
+ 
+   std::string st;
+   std::string part = "1234567890123456789012345678901234567890";
+   for (int i = 0; i < digits_overflow / part.size() + 1; ++i)
+     st += part;
+   std::stringbuf sb(st);
+   std::istream is(&sb);
+   T t;
+   is >> t;
+   VERIFY(is.fail());
+   return test;
+ }
+ 
+ bool test12()
+ {
+    bool test = true;
+    VERIFY(test12_aux<short>());
+    VERIFY(test12_aux<int>());
+    VERIFY(test12_aux<long>());
+    VERIFY(test12_aux<float>());
+    VERIFY(test12_aux<double>());
+    VERIFY(test12_aux<long double>());
+    return test;
+ }
+ 
  int main()
  {
    test01();
*************** int main()
*** 526,531 ****
--- 560,566 ----
    test10();
    
    test11();
+   test12();
    return 0;
  }
  


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