This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3] libstdc++/21209
- From: Paolo Carlini <pcarlini at suse dot de>
- To: "'gcc-patches at gcc dot gnu dot org'" <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 26 Apr 2005 11:32:28 +0200
- Subject: [v3] libstdc++/21209
Hi,
tested x86-linux, committed to mainline.
Paolo.
////////////////
2005-04-26 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/21209
* include/bits/locale_facets.tcc (_M_extract_int): Avoid signed
integer overflow, always use a suited unsigned type in the main
parsing loop.
(struct __to_unsigned_type): New.
* testsuite/22_locale/num_get/get/char/16.cc: New.
* testsuite/22_locale/num_get/get/wchar_t/16.cc: Likewise.
diff -prN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
*** libstdc++-v3-orig/include/bits/locale_facets.tcc Sun Apr 17 16:30:36 2005
--- libstdc++-v3/include/bits/locale_facets.tcc Mon Apr 25 23:34:20 2005
*************** namespace std
*** 440,445 ****
--- 440,459 ----
return __beg;
}
+ template<typename _ValueT>
+ struct __to_unsigned_type
+ { typedef _ValueT __type; };
+
+ template<>
+ struct __to_unsigned_type<long>
+ { typedef unsigned long __type; };
+
+ #ifdef _GLIBCXX_USE_LONG_LONG
+ template<>
+ struct __to_unsigned_type<long long>
+ { typedef unsigned long long __type; };
+ #endif
+
template<typename _CharT, typename _InIter>
template<typename _ValueT>
_InIter
*************** namespace std
*** 447,454 ****
_M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
ios_base::iostate& __err, _ValueT& __v) const
{
! typedef char_traits<_CharT> __traits_type;
! typedef typename numpunct<_CharT>::__cache_type __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc);
--- 461,469 ----
_M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
ios_base::iostate& __err, _ValueT& __v) const
{
! typedef char_traits<_CharT> __traits_type;
! typedef typename __to_unsigned_type<_ValueT>::__type __unsigned_type;
! typedef typename numpunct<_CharT>::__cache_type __cache_type;
__use_cache<__cache_type> __uc;
const locale& __loc = __io._M_getloc();
const __cache_type* __lc = __uc(__loc);
*************** namespace std
*** 536,638 ****
__found_grouping.reserve(32);
int __sep_pos = 0;
bool __overflow = false;
! _ValueT __result = 0;
const char_type* __q;
const char_type* __lit_zero = __lit + __num_base::_S_izero;
! if (__negative)
{
! const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
! while (!__testeof)
{
! // According to 22.2.2.1.2, p8-9, first look for thousands_sep
! // and decimal_point.
! if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
{
! // NB: Thousands separator at the beginning of a string
! // is a no-no, as is two consecutive thousands separators.
! if (__sep_pos)
! {
! __found_grouping += static_cast<char>(__sep_pos);
! __sep_pos = 0;
! }
! else
! {
! __err |= ios_base::failbit;
! break;
! }
}
! else if (__c == __lc->_M_decimal_point)
! break;
! else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
{
! int __digit = __q - __lit_zero;
! if (__digit > 15)
! __digit -= 6;
! if (__result < __min)
! __overflow = true;
! else
! {
! const _ValueT __new_result = (__result * __base
! - __digit);
! __overflow |= __new_result > __result;
! __result = __new_result;
! ++__sep_pos;
! }
}
- else
- // Not a valid input item.
- break;
-
- if (++__beg != __end)
- __c = *__beg;
- else
- __testeof = true;
}
! }
! else
! {
! const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
! while (!__testeof)
{
! if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
! {
! if (__sep_pos)
! {
! __found_grouping += static_cast<char>(__sep_pos);
! __sep_pos = 0;
! }
! else
! {
! __err |= ios_base::failbit;
! break;
! }
! }
! else if (__c == __lc->_M_decimal_point)
! break;
! else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
{
! int __digit = __q - __lit_zero;
! if (__digit > 15)
! __digit -= 6;
! if (__result > __max)
! __overflow = true;
! else
! {
! const _ValueT __new_result = (__result * __base
! + __digit);
! __overflow |= __new_result < __result;
! __result = __new_result;
! ++__sep_pos;
! }
}
- else
- break;
-
- if (++__beg != __end)
- __c = *__beg;
- else
- __testeof = true;
}
}
// Digit grouping is checked. If grouping and found_grouping don't
--- 551,606 ----
__found_grouping.reserve(32);
int __sep_pos = 0;
bool __overflow = false;
! const __unsigned_type __max = __negative ?
! -numeric_limits<_ValueT>::min() : numeric_limits<_ValueT>::max();
! const __unsigned_type __smax = __max / __base;
! __unsigned_type __result = 0;
const char_type* __q;
const char_type* __lit_zero = __lit + __num_base::_S_izero;
! while (!__testeof)
{
! // According to 22.2.2.1.2, p8-9, first look for thousands_sep
! // and decimal_point.
! if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
{
! // NB: Thousands separator at the beginning of a string
! // is a no-no, as is two consecutive thousands separators.
! if (__sep_pos)
{
! __found_grouping += static_cast<char>(__sep_pos);
! __sep_pos = 0;
}
! else
{
! __err |= ios_base::failbit;
! break;
}
}
! else if (__c == __lc->_M_decimal_point)
! break;
! else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
{
! int __digit = __q - __lit_zero;
! if (__digit > 15)
! __digit -= 6;
! if (__result > __smax)
! __overflow = true;
! else
{
! __result *= __base;
! __overflow |= __result > __max - __digit;
! __result += __digit;
! ++__sep_pos;
}
}
+ else
+ // Not a valid input item.
+ break;
+
+ if (++__beg != __end)
+ __c = *__beg;
+ else
+ __testeof = true;
}
// Digit grouping is checked. If grouping and found_grouping don't
*************** namespace std
*** 650,656 ****
if (!(__err & ios_base::failbit) && !__overflow
&& (__sep_pos || __found_zero || __found_grouping.size()))
! __v = __result;
else
__err |= ios_base::failbit;
--- 618,624 ----
if (!(__err & ios_base::failbit) && !__overflow
&& (__sep_pos || __found_zero || __found_grouping.size()))
! __v = __negative ? -__result : __result;
else
__err |= ios_base::failbit;
diff -prN libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/16.cc libstdc++-v3/testsuite/22_locale/num_get/get/char/16.cc
*** libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/16.cc Thu Jan 1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_get/get/char/16.cc Tue Apr 26 00:33:14 2005
***************
*** 0 ****
--- 1,202 ----
+ // 2005-04-26 Paolo Carlini <pcarlini@suse.de>
+
+ // Copyright (C) 2005 Free Software Foundation
+ //
+ // This file is part of the GNU ISO C++ Library. This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING. If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+
+ // 22.2.2.1.1 num_get members
+
+ #include <locale>
+ #include <sstream>
+ #include <limits>
+ #include <testsuite_hooks.h>
+
+ void test01()
+ {
+ using namespace std;
+ typedef istreambuf_iterator<char> iterator_type;
+
+ bool test __attribute__((unused)) = true;
+
+ stringstream ss;
+ const num_get<char>& ng = use_facet<num_get<char> >(ss.getloc());
+ ios_base::iostate err;
+ iterator_type end;
+
+ unsigned short us0, us1 = numeric_limits<unsigned short>::max();
+ unsigned int ui0, ui1 = numeric_limits<unsigned int>::max();
+ unsigned long ul0, ul1 = numeric_limits<unsigned long>::max();
+ long l01, l1 = numeric_limits<long>::max();
+ long l02, l2 = numeric_limits<long>::min();
+ #ifdef _GLIBCXX_USE_LONG_LONG
+ unsigned long long ull0, ull1 = numeric_limits<unsigned long long>::max();
+ long long ll01, ll1 = numeric_limits<long long>::max();
+ long long ll02, ll2 = numeric_limits<long long>::min();
+ #endif
+
+ const string empty;
+
+ us0 = 0;
+ ss << us1;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, us0);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( us0 == us1 );
+
+ us0 = 0;
+ ss.clear();
+ ss.str(empty);
+ ss << us1 << '0';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, us0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( us0 == 0 );
+
+ ui0 = 0U;
+ ss.clear();
+ ss.str(empty);
+ ss << ui1 << ' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ui0);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( ui0 == ui1 );
+
+ ui0 = 0U;
+ ss.clear();
+ ss.str(empty);
+ ss << ui1 << '1';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ui0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ui0 == 0U );
+
+ ul0 = 0UL;
+ ss.clear();
+ ss.str(empty);
+ ss << ul1;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ul0);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( ul0 == ul1 );
+
+ ul0 = 0UL;
+ ss.clear();
+ ss.str(empty);
+ ss << ul1 << '2';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ul0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ul0 == 0UL );
+
+ l01 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l1 << ' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l01);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( l01 == l1 );
+
+ l01 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l1 << '3';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l01);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( l01 == 0L );
+
+ l02 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l2;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l02);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( l02 == l2 );
+
+ l02 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l2 << '4';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l02);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( l02 == 0L );
+
+ #ifdef _GLIBCXX_USE_LONG_LONG
+ ull0 = 0ULL;
+ ss.clear();
+ ss.str(empty);
+ ss << ull1 << ' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ull0);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( ull0 == ull1 );
+
+ ull0 = 0ULL;
+ ss.clear();
+ ss.str(empty);
+ ss << ull1 << '5';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ull0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ull0 == 0ULL );
+
+ ll01 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll1;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll01);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( ll01 == ll1 );
+
+ ll01 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll1 << '6';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll01);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ll01 == 0LL );
+
+ ll02 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll2 << ' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll02);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( ll02 == ll2 );
+
+ ll02 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll2 << '7';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll02);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ll02 == 0LL );
+ #endif
+ }
+
+ int main()
+ {
+ test01();
+ return 0;
+ }
diff -prN libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/16.cc libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/16.cc
*** libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/16.cc Thu Jan 1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/16.cc Tue Apr 26 00:32:53 2005
***************
*** 0 ****
--- 1,202 ----
+ // 2005-04-26 Paolo Carlini <pcarlini@suse.de>
+
+ // Copyright (C) 2005 Free Software Foundation
+ //
+ // This file is part of the GNU ISO C++ Library. This library is free
+ // software; you can redistribute it and/or modify it under the
+ // terms of the GNU General Public License as published by the
+ // Free Software Foundation; either version 2, or (at your option)
+ // any later version.
+
+ // This library is distributed in the hope that it will be useful,
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ // GNU General Public License for more details.
+
+ // You should have received a copy of the GNU General Public License along
+ // with this library; see the file COPYING. If not, write to the Free
+ // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ // USA.
+
+ // 22.2.2.1.1 num_get members
+
+ #include <locale>
+ #include <sstream>
+ #include <limits>
+ #include <testsuite_hooks.h>
+
+ void test01()
+ {
+ using namespace std;
+ typedef istreambuf_iterator<wchar_t> iterator_type;
+
+ bool test __attribute__((unused)) = true;
+
+ wstringstream ss;
+ const num_get<wchar_t>& ng = use_facet<num_get<wchar_t> >(ss.getloc());
+ ios_base::iostate err;
+ iterator_type end;
+
+ unsigned short us0, us1 = numeric_limits<unsigned short>::max();
+ unsigned int ui0, ui1 = numeric_limits<unsigned int>::max();
+ unsigned long ul0, ul1 = numeric_limits<unsigned long>::max();
+ long l01, l1 = numeric_limits<long>::max();
+ long l02, l2 = numeric_limits<long>::min();
+ #ifdef _GLIBCXX_USE_LONG_LONG
+ unsigned long long ull0, ull1 = numeric_limits<unsigned long long>::max();
+ long long ll01, ll1 = numeric_limits<long long>::max();
+ long long ll02, ll2 = numeric_limits<long long>::min();
+ #endif
+
+ const wstring empty;
+
+ us0 = 0;
+ ss << us1;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, us0);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( us0 == us1 );
+
+ us0 = 0;
+ ss.clear();
+ ss.str(empty);
+ ss << us1 << L'0';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, us0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( us0 == 0 );
+
+ ui0 = 0U;
+ ss.clear();
+ ss.str(empty);
+ ss << ui1 << ' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ui0);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( ui0 == ui1 );
+
+ ui0 = 0U;
+ ss.clear();
+ ss.str(empty);
+ ss << ui1 << L'1';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ui0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ui0 == 0U );
+
+ ul0 = 0UL;
+ ss.clear();
+ ss.str(empty);
+ ss << ul1;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ul0);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( ul0 == ul1 );
+
+ ul0 = 0UL;
+ ss.clear();
+ ss.str(empty);
+ ss << ul1 << L'2';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ul0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ul0 == 0UL );
+
+ l01 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l1 << L' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l01);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( l01 == l1 );
+
+ l01 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l1 << L'3';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l01);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( l01 == 0L );
+
+ l02 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l2;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l02);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( l02 == l2 );
+
+ l02 = 0L;
+ ss.clear();
+ ss.str(empty);
+ ss << l2 << L'4';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, l02);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( l02 == 0L );
+
+ #ifdef _GLIBCXX_USE_LONG_LONG
+ ull0 = 0ULL;
+ ss.clear();
+ ss.str(empty);
+ ss << ull1 << L' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ull0);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( ull0 == ull1 );
+
+ ull0 = 0ULL;
+ ss.clear();
+ ss.str(empty);
+ ss << ull1 << L'5';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ull0);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ull0 == 0ULL );
+
+ ll01 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll1;
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll01);
+ VERIFY( err == ios_base::eofbit );
+ VERIFY( ll01 == ll1 );
+
+ ll01 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll1 << L'6';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll01);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ll01 == 0LL );
+
+ ll02 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll2 << L' ';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll02);
+ VERIFY( err == ios_base::goodbit );
+ VERIFY( ll02 == ll2 );
+
+ ll02 = 0LL;
+ ss.clear();
+ ss.str(empty);
+ ss << ll2 << L'7';
+ err = ios_base::goodbit;
+ end = ng.get(ss.rdbuf(), 0, ss, err, ll02);
+ VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
+ VERIFY( ll02 == 0LL );
+ #endif
+ }
+
+ int main()
+ {
+ test01();
+ return 0;
+ }