diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index cec2c50..0927e39 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -18,7 +18,7 @@ // with additional fixes and suggestions from Gennaro Prota, // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury and other Boosters +// Cheng Yang, Matthew Bradbury, David W. Birdsall and other Boosters // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012 #include @@ -591,6 +591,7 @@ namespace boost value = *end - czero; --end; T multiplier = 1; + bool multiplier_overflowed = false; #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE std::locale loc; @@ -613,12 +614,17 @@ namespace boost for(;end>=begin; --end) { if (remained) { - T const new_sub_value = multiplier * 10 * (*end - czero); + T const multiplier_10 = multiplier * 10; + if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true; + + T const dig_value = *end - czero; + T const new_sub_value = multiplier_10 * dig_value; if (*end < czero || *end >= czero + 10 /* detecting overflow */ - || new_sub_value/10 != multiplier * (*end - czero) + || (dig_value && new_sub_value / dig_value != multiplier_10) || static_cast((std::numeric_limits::max)()-new_sub_value) < value + || (multiplier_overflowed && dig_value) ) return false; @@ -656,12 +662,17 @@ namespace boost { while ( begin <= end ) { - T const new_sub_value = multiplier * 10 * (*end - czero); + T const multiplier_10 = multiplier * 10; + if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true; + + T const dig_value = *end - czero; + T const new_sub_value = multiplier_10 * dig_value; if (*end < czero || *end >= czero + 10 /* detecting overflow */ - || new_sub_value/10 != multiplier * (*end - czero) + || (dig_value && new_sub_value / dig_value != multiplier_10) || static_cast((std::numeric_limits::max)()-new_sub_value) < value + || (multiplier_overflowed && dig_value) ) return false; diff --git a/lexical_cast_test.cpp b/lexical_cast_test.cpp index faeaa93..4e9ec90 100644 --- a/lexical_cast_test.cpp +++ b/lexical_cast_test.cpp @@ -796,6 +796,17 @@ void test_conversion_from_to_integral() BOOST_CHECK_THROW(lexical_cast("+-9"), bad_lexical_cast); // test_conversion_from_to_integral_for_locale + // Overflow test case from David W. Birdsall + std::string must_owerflow_str = "160000000000000000000"; + std::string must_owerflow_negative_str = "-160000000000000000000"; + for (int i = 0; i < 15; ++i) { + BOOST_CHECK_THROW(lexical_cast(must_owerflow_str), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(must_owerflow_negative_str), bad_lexical_cast); + + must_owerflow_str += '0'; + must_owerflow_negative_str += '0'; + } + typedef std::numpunct numpunct; restore_oldloc guard;