From 9a6d983ee55ba495b3b5f9055fa86c7fd7018c6c Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Thu, 5 Jan 2012 12:09:15 +0000 Subject: [PATCH] Fixes #6193 [SVN r76318] --- include/boost/lexical_cast.hpp | 21 ++++++++++++++++----- lexical_cast_test.cpp | 11 +++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) 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;