From mboxrd@z Thu Jan 1 00:00:00 1970 From: Philip Martin To: nobody@gcc.gnu.org Cc: gcc-prs@gcc.gnu.org Subject: Re: libstdc++/3720 is a 2.95 regression [PATCH] Date: Fri, 24 Aug 2001 08:26:00 -0000 Message-id: <20010824152601.28541.qmail@sourceware.cygnus.com> X-SW-Source: 2001-08/msg00627.html List-Id: The following reply was made to PR libstdc++/3720; it has been noted by GNATS. From: Philip Martin To: gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org, schmid@snake.iap.physik.tu-darmstadt.de, gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Cc: Subject: Re: libstdc++/3720 is a 2.95 regression [PATCH] Date: 24 Aug 2001 16:16:03 +0100 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 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. 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 + + 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 // For struct tm #include // For ios_base + #include // For vector #ifdef _GLIBCPP_USE_WCHAR_T # include // For codecvt # include // 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& __xtrc, int& __base, bool __fp = true) const; virtual iter_type *************** namespace std *** 714,720 **** num_get >:: _M_extract(istreambuf_iterator __beg, istreambuf_iterator __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 >:: _M_extract(istreambuf_iterator __beg, istreambuf_iterator __end, ios_base& __io, ! ios_base::iostate& __err, vector& __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& /*__xtrc*/, int& /*__base*/, bool /*__fp*/) const { // XXX Not currently done: need to expand upon char version below. *************** namespace std *** 262,268 **** num_get >:: _M_extract(istreambuf_iterator __beg, istreambuf_iterator __end, ios_base& __io, ! ios_base::iostate& __err, char* __xtrc, int& __base, bool __fp) const; #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS --- 262,268 ---- num_get >:: _M_extract(istreambuf_iterator __beg, istreambuf_iterator __end, ios_base& __io, ! ios_base::iostate& __err, vector& __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 __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(__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 __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(__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(__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 __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(__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 __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 __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(__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 __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(__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(__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 __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(__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 __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 __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 __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(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(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 __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 __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 __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(__p) != __traits_type::eof()) --- 676,682 ---- // Stage 3: store results. long double __ld; ! int __p = sscanf(&__xtrc[0], __conv, &__ld); if (__p && static_cast(__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(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 __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(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 >, __normal_iterator >, locale::facet* const&); + + template + void + std::vector::_M_insert_aux( + std::__normal_iterator > >, + 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 >:: _M_extract(istreambuf_iterator __beg, istreambuf_iterator __end, ios_base& __io, ! ios_base::iostate& __err, char* __xtrc, int& __base, bool __fp) const { typedef _Format_cache __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 >:: _M_extract(istreambuf_iterator __beg, istreambuf_iterator __end, ios_base& __io, ! ios_base::iostate& __err, vector& __xtrc, int& __base, bool __fp) const { typedef _Format_cache __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 + bool test12_aux() + { + bool test = true; + + // this many digits will overflow + int digits_overflow = std::numeric_limits::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()); + VERIFY(test12_aux()); + VERIFY(test12_aux()); + VERIFY(test12_aux()); + VERIFY(test12_aux()); + VERIFY(test12_aux()); + return test; + } + int main() { test01(); *************** int main() *** 526,531 **** --- 560,566 ---- test10(); test11(); + test12(); return 0; }