aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
authorPaolo Carlini <pcarlini@suse.de>2005-04-26 09:31:07 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2005-04-26 09:31:07 +0000
commit44ecf603649098d1d89bd855155a215507bf9e86 (patch)
tree90e9886d6ee581f71733aa43b16029cbbf1fb27a /libstdc++-v3/include
parentc579626684c724b226892b0869316fd1ed7ad350 (diff)
downloadgcc-44ecf603649098d1d89bd855155a215507bf9e86.zip
gcc-44ecf603649098d1d89bd855155a215507bf9e86.tar.gz
gcc-44ecf603649098d1d89bd855155a215507bf9e86.tar.bz2
re PR libstdc++/21209 (signed integer overflow in num_get<>::_M_extract_int)
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. From-SVN: r98768
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc142
1 files changed, 55 insertions, 87 deletions
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index b558237..436fe9d 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -440,6 +440,20 @@ namespace std
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
@@ -447,8 +461,9 @@ namespace std
_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;
+ 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);
@@ -536,103 +551,56 @@ namespace std
__found_grouping.reserve(32);
int __sep_pos = 0;
bool __overflow = false;
- _ValueT __result = 0;
+ 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;
- if (__negative)
+ while (!__testeof)
{
- 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)
{
- // 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)
{
- // 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;
- }
+ __found_grouping += static_cast<char>(__sep_pos);
+ __sep_pos = 0;
}
- else if (__c == __lc->_M_decimal_point)
- break;
- else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
+ else
{
- 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;
- }
+ __err |= ios_base::failbit;
+ break;
}
- 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)
+ else if (__c == __lc->_M_decimal_point)
+ break;
+ else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
{
- 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 > __smax)
+ __overflow = true;
+ else
{
- 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;
- }
+ __result *= __base;
+ __overflow |= __result > __max - __digit;
+ __result += __digit;
+ ++__sep_pos;
}
- else
- break;
-
- if (++__beg != __end)
- __c = *__beg;
- else
- __testeof = true;
}
+ 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
@@ -650,7 +618,7 @@ namespace std
if (!(__err & ios_base::failbit) && !__overflow
&& (__sep_pos || __found_zero || __found_grouping.size()))
- __v = __result;
+ __v = __negative ? -__result : __result;
else
__err |= ios_base::failbit;