From dbb6ef424f6b6dd66a59176bb1205a0d6aacaf6f Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Tue, 7 May 2019 12:06:05 +0200 Subject: [PATCH 1/8] Fix any_range with non-reference references can cause UB --- .../range/detail/any_iterator_interface.hpp | 26 ++++---- test/Jamfile.v2 | 1 + test/adaptor_test/type_erased_transformed.cpp | 66 +++++++++++++++++++ 3 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 test/adaptor_test/type_erased_transformed.cpp diff --git a/include/boost/range/detail/any_iterator_interface.hpp b/include/boost/range/detail/any_iterator_interface.hpp index cd56714..9310038 100644 --- a/include/boost/range/detail/any_iterator_interface.hpp +++ b/include/boost/range/detail/any_iterator_interface.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -35,15 +36,18 @@ namespace boost }; template - struct mutable_reference_type_generator + struct reference_as_value_type_generator { typedef typename mpl::if_< - typename mpl::and_< - typename is_const::type, - typename mpl::not_::type>::type + typename is_copy_constructible< + typename remove_const< + typename remove_reference::type + >::type >::type, - T, - typename add_reference::type + typename remove_const< + typename remove_reference::type + >::type, + T >::type type; }; @@ -53,16 +57,12 @@ namespace boost > struct any_incrementable_iterator_interface { - typedef typename mutable_reference_type_generator< - Reference - >::type reference; - + typedef Reference reference; typedef typename const_reference_type_generator< Reference >::type const_reference; - - typedef typename remove_const< - typename remove_reference::type + typedef typename reference_as_value_type_generator< + Reference >::type reference_as_value_type; typedef Buffer buffer_type; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b195926..cd2774e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -81,6 +81,7 @@ test-suite range : [ range-test adaptor_test/type_erased_forward ] [ range-test adaptor_test/type_erased_bidirectional ] [ range-test adaptor_test/type_erased_random_access ] + [ range-test adaptor_test/type_erased_transformed ] [ range-test adaptor_test/uniqued ] [ range-test adaptor_test/adjacent_filtered_example ] [ range-test adaptor_test/copied_example ] diff --git a/test/adaptor_test/type_erased_transformed.cpp b/test/adaptor_test/type_erased_transformed.cpp new file mode 100644 index 0000000..936d432 --- /dev/null +++ b/test/adaptor_test/type_erased_transformed.cpp @@ -0,0 +1,66 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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 +#include +#include +#include "type_erased_test.hpp" + +#include + +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +typedef boost::any_range< + int, + boost::random_access_traversal_tag, + int, + std::ptrdiff_t +> any_integer_value_range; + +struct get_fn +{ + boost::int32_t operator()(const MockType& val) const + { + return val.get(); + } +}; + +int accumulate_any_integer_value_range(any_integer_value_range rng) +{ + return boost::accumulate(rng, 0); +} + +void test_type_erased_transformed() +{ + std::vector v{1,2,3,4,5}; + + const int sum = accumulate_any_integer_value_range( + v | boost::adaptors::transformed(get_fn())); + + BOOST_CHECK_EQUAL(15, sum); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_transformed"); + + test->add( + BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_type_erased_transformed)); + + return test; +} From ce24356018eb522840d075c8a81e98b44bdd18e9 Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Tue, 7 May 2019 15:03:56 +0200 Subject: [PATCH 2/8] Replace is_copy_constructible with is_abstract (for pre C++11) --- include/boost/range/detail/any_iterator_interface.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/range/detail/any_iterator_interface.hpp b/include/boost/range/detail/any_iterator_interface.hpp index 9310038..38b307f 100644 --- a/include/boost/range/detail/any_iterator_interface.hpp +++ b/include/boost/range/detail/any_iterator_interface.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -39,15 +39,15 @@ namespace boost struct reference_as_value_type_generator { typedef typename mpl::if_< - typename is_copy_constructible< + typename is_abstract< typename remove_const< typename remove_reference::type >::type >::type, + T, typename remove_const< typename remove_reference::type - >::type, - T + >::type >::type type; }; From 3496282d3bb6b088348f199434067f4f8f99808c Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Tue, 7 May 2019 17:01:02 +0200 Subject: [PATCH 3/8] Remove usage of initializer_list in test --- test/adaptor_test/type_erased_transformed.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/adaptor_test/type_erased_transformed.cpp b/test/adaptor_test/type_erased_transformed.cpp index 936d432..20a8696 100644 --- a/test/adaptor_test/type_erased_transformed.cpp +++ b/test/adaptor_test/type_erased_transformed.cpp @@ -41,7 +41,7 @@ int accumulate_any_integer_value_range(any_integer_value_range rng) void test_type_erased_transformed() { - std::vector v{1,2,3,4,5}; + std::vector v(5, MockType(3)); const int sum = accumulate_any_integer_value_range( v | boost::adaptors::transformed(get_fn())); From 911d8a427d05b1665910267fd6bdd715bad0e14f Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Tue, 7 May 2019 17:17:50 +0200 Subject: [PATCH 4/8] Add result_type typedef in tests --- test/adaptor_test/type_erased_transformed.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/adaptor_test/type_erased_transformed.cpp b/test/adaptor_test/type_erased_transformed.cpp index 20a8696..1b38261 100644 --- a/test/adaptor_test/type_erased_transformed.cpp +++ b/test/adaptor_test/type_erased_transformed.cpp @@ -28,6 +28,7 @@ typedef boost::any_range< struct get_fn { + typedef boost::int32_t result_type; boost::int32_t operator()(const MockType& val) const { return val.get(); From 9f03cc44d8f7d228d4fe4dcdcedc0435c6413e98 Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Wed, 8 May 2019 09:58:37 +0200 Subject: [PATCH 5/8] Add is_copy_constructible for >= C++11 --- .../range/detail/any_iterator_interface.hpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/include/boost/range/detail/any_iterator_interface.hpp b/include/boost/range/detail/any_iterator_interface.hpp index 38b307f..6c218e8 100644 --- a/include/boost/range/detail/any_iterator_interface.hpp +++ b/include/boost/range/detail/any_iterator_interface.hpp @@ -12,9 +12,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -38,16 +40,17 @@ namespace boost template struct reference_as_value_type_generator { + typedef typename remove_const< + typename remove_reference::type + >::type const_reference_stripped_type; + typedef typename mpl::if_< - typename is_abstract< - typename remove_const< - typename remove_reference::type - >::type + typename mpl::or_< + mpl::not_::type>, + typename is_copy_constructible::type >::type, - T, - typename remove_const< - typename remove_reference::type - >::type + const_reference_stripped_type, + T >::type type; }; From 1bf2db29c0f2fc019778a027ecdbe74d59a83078 Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Wed, 8 May 2019 17:21:45 +0200 Subject: [PATCH 6/8] Replace is_copy_constructible and is_abstract with is_convertible --- .../range/detail/any_iterator_interface.hpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/include/boost/range/detail/any_iterator_interface.hpp b/include/boost/range/detail/any_iterator_interface.hpp index 6c218e8..6135474 100644 --- a/include/boost/range/detail/any_iterator_interface.hpp +++ b/include/boost/range/detail/any_iterator_interface.hpp @@ -13,12 +13,9 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include -#include #include namespace boost @@ -40,16 +37,11 @@ namespace boost template struct reference_as_value_type_generator { - typedef typename remove_const< - typename remove_reference::type - >::type const_reference_stripped_type; + typedef typename decay::type decayed_type; typedef typename mpl::if_< - typename mpl::or_< - mpl::not_::type>, - typename is_copy_constructible::type - >::type, - const_reference_stripped_type, + typename is_convertible::type, + decayed_type, T >::type type; }; From 6b3750f209ffdcbfe7018566250731cea0c55fbb Mon Sep 17 00:00:00 2001 From: Max Jendruk Date: Wed, 8 May 2019 22:43:09 +0200 Subject: [PATCH 7/8] Remove unused include --- include/boost/range/detail/any_iterator_interface.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/range/detail/any_iterator_interface.hpp b/include/boost/range/detail/any_iterator_interface.hpp index 6135474..893a09b 100644 --- a/include/boost/range/detail/any_iterator_interface.hpp +++ b/include/boost/range/detail/any_iterator_interface.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include From 21a06a93aa62f30bf2962d2fcf5900f6fa1e93bd Mon Sep 17 00:00:00 2001 From: "code@jendruk.com" Date: Fri, 31 May 2019 10:46:04 +0200 Subject: [PATCH 8/8] Replace decay with remove_reference / remove_const --- include/boost/range/detail/any_iterator_interface.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/boost/range/detail/any_iterator_interface.hpp b/include/boost/range/detail/any_iterator_interface.hpp index 6135474..d3b21ea 100644 --- a/include/boost/range/detail/any_iterator_interface.hpp +++ b/include/boost/range/detail/any_iterator_interface.hpp @@ -13,9 +13,9 @@ #include #include #include -#include #include #include +#include #include namespace boost @@ -37,11 +37,13 @@ namespace boost template struct reference_as_value_type_generator { - typedef typename decay::type decayed_type; + typedef typename remove_reference< + typename remove_const::type + >::type value_type; typedef typename mpl::if_< - typename is_convertible::type, - decayed_type, + typename is_convertible::type, + value_type, T >::type type; };