Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r76355 - in branches/release: boost libs/conversion libs/conversion/test
From: antoshkka_at_[hidden]
Date: 2012-01-08 04:05:37


Author: apolukhin
Date: 2012-01-08 04:05:35 EST (Sun, 08 Jan 2012)
New Revision: 76355
URL: http://svn.boost.org/trac/boost/changeset/76355

Log:
Merge from trunk r76354
(Fixes overflow detection, pointers casts)
Added:
   branches/release/libs/conversion/test/lexical_cast_pointers_test.cpp (contents, props changed)
Text files modified:
   branches/release/boost/lexical_cast.hpp | 48 ++++++++++++++++++++++++++++++---------
   branches/release/libs/conversion/lexical_cast_test.cpp | 11 +++++++++
   branches/release/libs/conversion/test/Jamfile.v2 | 1
   3 files changed, 49 insertions(+), 11 deletions(-)

Modified: branches/release/boost/lexical_cast.hpp
==============================================================================
--- branches/release/boost/lexical_cast.hpp (original)
+++ branches/release/boost/lexical_cast.hpp 2012-01-08 04:05:35 EST (Sun, 08 Jan 2012)
@@ -18,8 +18,8 @@
 // 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
-// when: November 2000, March 2003, June 2005, June 2006, March 2011
+// Cheng Yang, Matthew Bradbury, David W. Birdsall and other Boosters
+// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012
 
 #include <climits>
 #include <cstddef>
@@ -591,6 +591,7 @@
             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 @@
                     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<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
+ || (multiplier_overflowed && dig_value)
                                     )
                                 return false;
 
@@ -656,12 +662,17 @@
             {
                 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<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
+ || (multiplier_overflowed && dig_value)
                             )
                         return false;
 
@@ -1822,6 +1833,24 @@
                     deduce_char_traits<char_type,Target,Source>::type traits;
 
                 typedef BOOST_DEDUCED_TYPENAME remove_pointer<src >::type removed_ptr_t;
+
+ // is_char_types_match variable value can be computed via
+ // sizeof(char_type) == sizeof(removed_ptr_t). But when
+ // removed_ptr_t is an incomplete type or void*, compilers
+ // produce warnings or errors.
+ const bool is_char_types_match =
+ (::boost::type_traits::ice_or<
+ ::boost::type_traits::ice_and<
+ ::boost::type_traits::ice_eq<sizeof(char_type), sizeof(char) >::value,
+ ::boost::type_traits::ice_or<
+ ::boost::is_same<char, removed_ptr_t>::value,
+ ::boost::is_same<unsigned char, removed_ptr_t>::value,
+ ::boost::is_same<signed char, removed_ptr_t>::value
+ >::value
+ >::value,
+ is_same<char_type, removed_ptr_t>::value
+ >::value);
+
                 const bool requires_stringbuf =
                         !(
                              ::boost::type_traits::ice_or<
@@ -1830,10 +1859,7 @@
                                  ::boost::type_traits::ice_and<
                                      is_pointer<src >::value,
                                      is_char_or_wchar<removed_ptr_t >::value,
- ::boost::type_traits::ice_eq<
- sizeof(char_type),
- sizeof(removed_ptr_t)
- >::value
+ is_char_types_match
>::value
>::value
                         );
@@ -2111,7 +2137,7 @@
 
 // Copyright Kevlin Henney, 2000-2005.
 // Copyright Alexander Nasonov, 2006-2010.
-// Copyright Antony Polukhin, 2011.
+// Copyright Antony Polukhin, 2011-2012.
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at

Modified: branches/release/libs/conversion/lexical_cast_test.cpp
==============================================================================
--- branches/release/libs/conversion/lexical_cast_test.cpp (original)
+++ branches/release/libs/conversion/lexical_cast_test.cpp 2012-01-08 04:05:35 EST (Sun, 08 Jan 2012)
@@ -796,6 +796,17 @@
     BOOST_CHECK_THROW(lexical_cast<T>("+-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<T>(must_owerflow_str), bad_lexical_cast);
+ BOOST_CHECK_THROW(lexical_cast<T>(must_owerflow_negative_str), bad_lexical_cast);
+
+ must_owerflow_str += '0';
+ must_owerflow_negative_str += '0';
+ }
+
     typedef std::numpunct<char> numpunct;
 
     restore_oldloc guard;

Modified: branches/release/libs/conversion/test/Jamfile.v2
==============================================================================
--- branches/release/libs/conversion/test/Jamfile.v2 (original)
+++ branches/release/libs/conversion/test/Jamfile.v2 2012-01-08 04:05:35 EST (Sun, 08 Jan 2012)
@@ -35,6 +35,7 @@
     [ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
     [ run lexical_cast_containers_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
     [ run lexical_cast_empty_input_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
+ [ run lexical_cast_pointers_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
     [ compile lexical_cast_typedefed_wchar_test.cpp : <toolset>msvc:<nowchar>on ]
     [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <toolset>msvc:<nowchar>on ]
   ;

Added: branches/release/libs/conversion/test/lexical_cast_pointers_test.cpp
==============================================================================
--- (empty file)
+++ branches/release/libs/conversion/test/lexical_cast_pointers_test.cpp 2012-01-08 04:05:35 EST (Sun, 08 Jan 2012)
@@ -0,0 +1,96 @@
+// Unit test for boost::lexical_cast.
+//
+// See http://www.boost.org for most recent version, including documentation.
+//
+// Copyright Antony Polukhin, 2012.
+//
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
+
+#include <boost/config.hpp>
+
+#if defined(__INTEL_COMPILER)
+#pragma warning(disable: 193 383 488 981 1418 1419)
+#elif defined(BOOST_MSVC)
+#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800)
+#endif
+
+#include <boost/lexical_cast.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace boost;
+
+#if defined(BOOST_NO_STRINGSTREAM)
+ typedef std::strstream ss_t;
+#else
+ typedef std::stringstream ss_t;
+#endif
+
+void test_void_pointers_conversions()
+{
+ void *p_to_null = NULL;
+ const void *cp_to_data = "Some data";
+ char nonconst_data[5];
+ void *p_to_data = nonconst_data;
+ ss_t ss;
+
+ ss << p_to_null;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_null), ss.str());
+ ss.str(std::string());
+
+ ss << cp_to_data;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cp_to_data), ss.str());
+ ss.str(std::string());
+
+ ss << p_to_data;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_data), ss.str());
+ ss.str(std::string());
+}
+
+struct incomplete_type;
+
+void test_incomplete_type_pointers_conversions()
+{
+ incomplete_type *p_to_null = NULL;
+ const incomplete_type *cp_to_data = NULL;
+ char nonconst_data[5];
+ incomplete_type *p_to_data = reinterpret_cast<incomplete_type*>(nonconst_data);
+ ss_t ss;
+
+ ss << p_to_null;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_null), ss.str());
+ ss.str(std::string());
+
+ ss << cp_to_data;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(cp_to_data), ss.str());
+ ss.str(std::string());
+
+ ss << p_to_data;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(p_to_data), ss.str());
+ ss.str(std::string());
+}
+
+struct ble;
+typedef struct ble *meh;
+std::ostream& operator <<(std::ostream &o, meh) {
+ o << "yay";
+ return o;
+}
+
+void test_inomplete_type_with_overloaded_ostream_op() {
+ meh heh = NULL;
+ ss_t ss;
+ ss << heh;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(heh), ss.str());
+}
+
+unit_test::test_suite *init_unit_test_suite(int, char *[])
+{
+ unit_test::test_suite *suite =
+ BOOST_TEST_SUITE("lexical_cast pinters test");
+ suite->add(BOOST_TEST_CASE(&test_void_pointers_conversions));
+ suite->add(BOOST_TEST_CASE(&test_incomplete_type_pointers_conversions));
+ suite->add(BOOST_TEST_CASE(&test_inomplete_type_with_overloaded_ostream_op));
+ return suite;
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk