mirror of
https://github.com/boostorg/conversion.git
synced 2025-08-03 06:24:34 +02:00
Merge from trunk r76354
(Fixes overflow detection, pointers casts) [SVN r76355]
This commit is contained in:
@@ -18,8 +18,8 @@
|
|||||||
// with additional fixes and suggestions from Gennaro Prota,
|
// with additional fixes and suggestions from Gennaro Prota,
|
||||||
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
|
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
|
||||||
// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
|
// 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
|
// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2012
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@@ -591,6 +591,7 @@ namespace boost
|
|||||||
value = *end - czero;
|
value = *end - czero;
|
||||||
--end;
|
--end;
|
||||||
T multiplier = 1;
|
T multiplier = 1;
|
||||||
|
bool multiplier_overflowed = false;
|
||||||
|
|
||||||
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
|
#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
|
||||||
std::locale loc;
|
std::locale loc;
|
||||||
@@ -613,12 +614,17 @@ namespace boost
|
|||||||
for(;end>=begin; --end)
|
for(;end>=begin; --end)
|
||||||
{
|
{
|
||||||
if (remained) {
|
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
|
if (*end < czero || *end >= czero + 10
|
||||||
/* detecting overflow */
|
/* 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
|
|| static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
|
||||||
|
|| (multiplier_overflowed && dig_value)
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -656,12 +662,17 @@ namespace boost
|
|||||||
{
|
{
|
||||||
while ( begin <= end )
|
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
|
if (*end < czero || *end >= czero + 10
|
||||||
/* detecting overflow */
|
/* 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
|
|| static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
|
||||||
|
|| (multiplier_overflowed && dig_value)
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1822,6 +1833,24 @@ namespace boost
|
|||||||
deduce_char_traits<char_type,Target,Source>::type traits;
|
deduce_char_traits<char_type,Target,Source>::type traits;
|
||||||
|
|
||||||
typedef BOOST_DEDUCED_TYPENAME remove_pointer<src >::type removed_ptr_t;
|
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 =
|
const bool requires_stringbuf =
|
||||||
!(
|
!(
|
||||||
::boost::type_traits::ice_or<
|
::boost::type_traits::ice_or<
|
||||||
@@ -1830,10 +1859,7 @@ namespace boost
|
|||||||
::boost::type_traits::ice_and<
|
::boost::type_traits::ice_and<
|
||||||
is_pointer<src >::value,
|
is_pointer<src >::value,
|
||||||
is_char_or_wchar<removed_ptr_t >::value,
|
is_char_or_wchar<removed_ptr_t >::value,
|
||||||
::boost::type_traits::ice_eq<
|
is_char_types_match
|
||||||
sizeof(char_type),
|
|
||||||
sizeof(removed_ptr_t)
|
|
||||||
>::value
|
|
||||||
>::value
|
>::value
|
||||||
>::value
|
>::value
|
||||||
);
|
);
|
||||||
@@ -2111,7 +2137,7 @@ namespace boost
|
|||||||
|
|
||||||
// Copyright Kevlin Henney, 2000-2005.
|
// Copyright Kevlin Henney, 2000-2005.
|
||||||
// Copyright Alexander Nasonov, 2006-2010.
|
// Copyright Alexander Nasonov, 2006-2010.
|
||||||
// Copyright Antony Polukhin, 2011.
|
// Copyright Antony Polukhin, 2011-2012.
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See
|
// Distributed under the Boost Software License, Version 1.0. (See
|
||||||
// accompanying file LICENSE_1_0.txt or copy at
|
// accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
@@ -796,6 +796,17 @@ void test_conversion_from_to_integral()
|
|||||||
BOOST_CHECK_THROW(lexical_cast<T>("+-9"), bad_lexical_cast);
|
BOOST_CHECK_THROW(lexical_cast<T>("+-9"), bad_lexical_cast);
|
||||||
// test_conversion_from_to_integral_for_locale
|
// 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;
|
typedef std::numpunct<char> numpunct;
|
||||||
|
|
||||||
restore_oldloc guard;
|
restore_oldloc guard;
|
||||||
|
@@ -35,6 +35,7 @@ test-suite conversion
|
|||||||
[ run lexical_cast_inf_nan_test.cpp ../../test/build//boost_unit_test_framework/<link>static ]
|
[ 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_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_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 ]
|
[ 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 ]
|
[ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/<link>static : : : <toolset>msvc:<nowchar>on ]
|
||||||
;
|
;
|
||||||
|
96
test/lexical_cast_pointers_test.cpp
Executable file
96
test/lexical_cast_pointers_test.cpp
Executable file
@@ -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;
|
||||||
|
}
|
Reference in New Issue
Block a user