From 672775545d356c936112636c3ace87af383e17bc Mon Sep 17 00:00:00 2001 From: Steven Watanabe Date: Wed, 9 Jun 2010 23:04:24 +0000 Subject: [PATCH] Avoid calling the formatter with an invalid match. Fixes #2777 [SVN r62695] --- .../algorithm/string/detail/find_format.hpp | 44 +++++---- .../string/detail/find_format_all.hpp | 50 ++++++---- .../string/detail/find_format_store.hpp | 13 ++- string/test/find_format_test.cpp | 98 +++++++++++++++---- 4 files changed, 147 insertions(+), 58 deletions(-) diff --git a/include/boost/algorithm/string/detail/find_format.hpp b/include/boost/algorithm/string/detail/find_format.hpp index 4014f38..8b9ad42 100644 --- a/include/boost/algorithm/string/detail/find_format.hpp +++ b/include/boost/algorithm/string/detail/find_format.hpp @@ -74,13 +74,17 @@ namespace boost { const InputT& Input, FormatterT Formatter, const FindResultT& FindResult ) - { - return ::boost::algorithm::detail::find_format_copy_impl2( - Output, - Input, - Formatter, - FindResult, - Formatter(FindResult) ); + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_copy_impl2( + Output, + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return std::copy( ::boost::begin(Input), ::boost::end(Input), Output ); + } } @@ -132,11 +136,15 @@ namespace boost { FormatterT Formatter, const FindResultT& FindResult) { - return ::boost::algorithm::detail::find_format_copy_impl2( - Input, - Formatter, - FindResult, - Formatter(FindResult) ); + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_copy_impl2( + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return Input; + } } // replace implementation ----------------------------------------------------// @@ -180,11 +188,13 @@ namespace boost { FormatterT Formatter, const FindResultT& FindResult) { - ::boost::algorithm::detail::find_format_impl2( - Input, - Formatter, - FindResult, - Formatter(FindResult) ); + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + ::boost::algorithm::detail::find_format_impl2( + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } } } // namespace detail diff --git a/include/boost/algorithm/string/detail/find_format_all.hpp b/include/boost/algorithm/string/detail/find_format_all.hpp index 07e6124..978710c 100644 --- a/include/boost/algorithm/string/detail/find_format_all.hpp +++ b/include/boost/algorithm/string/detail/find_format_all.hpp @@ -84,14 +84,18 @@ namespace boost { FinderT Finder, FormatterT Formatter, const FindResultT& FindResult ) - { - return ::boost::algorithm::detail::find_format_all_copy_impl2( - Output, - Input, - Finder, - Formatter, - FindResult, - Formatter(FindResult) ); + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_all_copy_impl2( + Output, + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return std::copy( ::boost::begin(Input), ::boost::end(Input), Output ); + } } // find_format_all_copy implementation ----------------------------------------------// @@ -156,12 +160,16 @@ namespace boost { FormatterT Formatter, const FindResultT& FindResult) { - return ::boost::algorithm::detail::find_format_all_copy_impl2( - Input, - Finder, - Formatter, - FindResult, - Formatter(FindResult) ); + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_all_copy_impl2( + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return Input; + } } // find_format_all implementation ------------------------------------------------// @@ -248,12 +256,14 @@ namespace boost { FormatterT Formatter, FindResultT FindResult) { - ::boost::algorithm::detail::find_format_all_impl2( - Input, - Finder, - Formatter, - FindResult, - Formatter(FindResult) ); + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + ::boost::algorithm::detail::find_format_all_impl2( + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } } } // namespace detail diff --git a/include/boost/algorithm/string/detail/find_format_store.hpp b/include/boost/algorithm/string/detail/find_format_store.hpp index 2260fc2..776353f 100644 --- a/include/boost/algorithm/string/detail/find_format_store.hpp +++ b/include/boost/algorithm/string/detail/find_format_store.hpp @@ -52,7 +52,9 @@ namespace boost { find_format_store& operator=( FindResultT FindResult ) { iterator_range::operator=(FindResult); - m_FormatResult=m_Formatter(FindResult); + if( !this->empty() ) { + m_FormatResult=m_Formatter(FindResult); + } return *this; } @@ -68,6 +70,15 @@ namespace boost { const formatter_type& m_Formatter; }; + template + bool check_find_result(InputT& Input, FindResultT& FindResult) + { + typedef BOOST_STRING_TYPENAME + range_const_iterator::type input_iterator_type; + iterator_range ResultRange(FindResult); + return !ResultRange.empty(); + } + #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) #pragma warning(pop) #endif diff --git a/string/test/find_format_test.cpp b/string/test/find_format_test.cpp index 803c178..4201e1e 100644 --- a/string/test/find_format_test.cpp +++ b/string/test/find_format_test.cpp @@ -16,6 +16,31 @@ #include +// We're only using const_formatter. +template +struct formatter_result { + typedef boost::iterator_range type; +}; + +template +struct checked_formatter { +public: + checked_formatter(const Formatter& formatter) : formatter_(formatter) {} + template< typename T > + typename formatter_result::type operator()( const T & s ) const { + BOOST_CHECK( !s.empty() ); + return formatter_(s); + } +private: + Formatter formatter_; +}; + +template +checked_formatter +make_checked_formatter(const Formatter& formatter) { + return checked_formatter(formatter); +} + void find_format_test() { const std::string source = "$replace $replace"; @@ -23,36 +48,53 @@ void find_format_test() std::string output(80, '\0'); std::string::iterator pos = - boost::find_format_copy(output.begin(), - source, - boost::first_finder("$replace"), - boost::const_formatter("ok")); + boost::find_format_copy( + output.begin(), + source, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); BOOST_CHECK(pos == output.begin() + expected.size()); output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); BOOST_CHECK_EQUAL(output, expected); - output = boost::find_format_copy(source, boost::first_finder("$replace"), boost::const_formatter("ok")); + output = + boost::find_format_copy( + source, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); BOOST_CHECK_EQUAL(output, expected); // now try finding a string that doesn't exist output.resize(80); - pos = boost::find_format_copy(output.begin(), - source, - boost::first_finder("$noreplace"), - boost::const_formatter("bad")); + pos = + boost::find_format_copy( + output.begin(), + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); BOOST_CHECK(pos == output.begin() + source.size()); output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); BOOST_CHECK_EQUAL(output, source); - output = boost::find_format_copy(source, boost::first_finder("$noreplace"), boost::const_formatter("bad")); + output = + boost::find_format_copy( + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); BOOST_CHECK_EQUAL(output, source); // in place version output = source; - boost::find_format(output, boost::first_finder("$replace"), boost::const_formatter("ok")); + boost::find_format( + output, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); BOOST_CHECK_EQUAL(output, expected); output = source; - boost::find_format(output, boost::first_finder("$noreplace"), boost::const_formatter("bad")); + boost::find_format( + output, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); BOOST_CHECK_EQUAL(output, source); } @@ -71,28 +113,44 @@ void find_format_all_test() output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); BOOST_CHECK_EQUAL(output, expected); - output = boost::find_format_all_copy(source, boost::first_finder("$replace"), boost::const_formatter("ok")); + output = + boost::find_format_all_copy( + source, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); BOOST_CHECK_EQUAL(output, expected); // now try finding a string that doesn't exist output.resize(80); - pos = boost::find_format_all_copy(output.begin(), - source, - boost::first_finder("$noreplace"), - boost::const_formatter("bad")); + pos = + boost::find_format_all_copy( + output.begin(), + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); BOOST_CHECK(pos == output.begin() + source.size()); output.erase(std::remove(output.begin(), output.end(), '\0'), output.end()); BOOST_CHECK_EQUAL(output, source); - output = boost::find_format_all_copy(source, boost::first_finder("$noreplace"), boost::const_formatter("bad")); + output = + boost::find_format_all_copy( + source, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); BOOST_CHECK_EQUAL(output, source); // in place version output = source; - boost::find_format_all(output, boost::first_finder("$replace"), boost::const_formatter("ok")); + boost::find_format_all( + output, + boost::first_finder("$replace"), + make_checked_formatter(boost::const_formatter("ok"))); BOOST_CHECK_EQUAL(output, expected); output = source; - boost::find_format_all(output, boost::first_finder("$noreplace"), boost::const_formatter("bad")); + boost::find_format_all( + output, + boost::first_finder("$noreplace"), + make_checked_formatter(boost::const_formatter("bad"))); BOOST_CHECK_EQUAL(output, source); }