From a0a621ac960e773f86a5c6ba84da2bf2d4d839ce Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Fri, 24 Jan 2025 07:43:53 -0600 Subject: [PATCH] GH-1091 Improve logic. Make sure it doesn't throw for use on incoming addresses. --- .../include/eosio/net_plugin/net_utils.hpp | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/plugins/net_plugin/include/eosio/net_plugin/net_utils.hpp b/plugins/net_plugin/include/eosio/net_plugin/net_utils.hpp index 0dd4db5ff8..6efb1f62e1 100644 --- a/plugins/net_plugin/include/eosio/net_plugin/net_utils.hpp +++ b/plugins/net_plugin/include/eosio/net_plugin/net_utils.hpp @@ -41,24 +41,32 @@ namespace detail { } /// @return host, port, remainder - inline std::tuple split_host_port_remainder(const std::string& peer_add) { + inline std::tuple split_host_port_remainder(const std::string& peer_add, bool should_throw) { using std::string; // host:port[:trx|:blk][:] if (peer_add.empty()) return {}; - string::size_type p = peer_add[0] == '[' ? peer_add.find(']') : 0; - if (p == 0) { - if( auto colon_count = std::count(peer_add.begin(), peer_add.end(), ':'); colon_count >= 7 ) { - EOS_ASSERT( colon_count <= 2, chain::plugin_config_exception, - "Invalid address specification ${a}; IPv6 addresses must be enclosed in square brackets.", ("a", peer_add)); + auto colon_count = std::count(peer_add.begin(), peer_add.end(), ':'); + string::size_type end_bracket = 0; + if (peer_add[0] == '[') { + end_bracket = peer_add.find(']'); + if (end_bracket == string::npos) { + EOS_ASSERT(!should_throw, chain::plugin_config_exception, + "Invalid address specification ${a}, IPv6 no closing square bracket", ("a", peer_add) ); + return {}; } + } else if (colon_count >= 7) { + EOS_ASSERT(!should_throw, chain::plugin_config_exception, + "Invalid address specification ${a}; IPv6 addresses must be enclosed in square brackets.", ("a", peer_add)); + return {}; + } - string::size_type colon = p != string::npos ? peer_add.find(':', p) : string::npos; + string::size_type colon = peer_add.find(':', end_bracket+1); if (colon == string::npos || colon == 0) { return {}; } string::size_type colon2 = peer_add.find(':', colon + 1); - string host = (p > 0) ? peer_add.substr( 0, p+1 ) : peer_add.substr( 0, colon ); + string host = (end_bracket > 0) ? peer_add.substr( 0, end_bracket+1 ) : peer_add.substr( 0, colon ); string port = peer_add.substr( colon + 1, colon2 == string::npos ? string::npos : colon2 - (colon + 1)); string remainder = colon2 == string::npos ? "" : peer_add.substr( colon2 + 1 ); return {std::move(host), std::move(port), std::move(remainder)}; @@ -66,13 +74,15 @@ namespace detail { } // namespace detail - /// @return host, port, type + /// @return host, port, type. returns empty on invalid peer_add, does not throw inline std::tuple split_host_port_type(const std::string& peer_add) { + using std::string; // host:port[:trx|:blk][:] // rate is discarded if (peer_add.empty()) return {}; - auto [host, port, remainder] = detail::split_host_port_remainder(peer_add); + constexpr bool should_throw = false; + auto [host, port, remainder] = detail::split_host_port_remainder(peer_add, should_throw); if (host.empty()) return {}; string::size_type end = remainder.find_first_of( " :+=.,<>!$%^&(*)|-#@\t" ); // future proof by including most symbols without using regex @@ -82,9 +92,10 @@ namespace detail { } /// @return listen address, type [trx|blk], and block sync rate limit (in bytes/sec) of address string + /// @throws chain::plugin_config_exception on invalid address inline std::tuple parse_listen_address( const std::string& address ) { - - auto [host, port, remainder] = detail::split_host_port_remainder(address); + constexpr bool should_throw = true; + auto [host, port, remainder] = detail::split_host_port_remainder(address, should_throw); auto listen_addr = host + ":" + port; auto limit = remainder; auto last_colon_location = remainder.rfind(':'); @@ -96,24 +107,4 @@ namespace detail { return {std::move(listen_addr), block_sync_rate_limit}; } - inline std::tuple split_host_xport_type(const std::string& peer_add) { - using std::string; - // host:port:[|] - if (peer_add.empty()) return {}; - - string::size_type p = peer_add[0] == '[' ? peer_add.find(']') : 0; - string::size_type colon = p != string::npos ? peer_add.find(':', p) : string::npos; - if (colon == string::npos || colon == 0) { - return {}; - } - string::size_type colon2 = peer_add.find(':', colon + 1); - string::size_type end = colon2 == string::npos - ? string::npos : peer_add.find_first_of( " :+=.,<>!$%^&(*)|-#@\t", colon2 + 1 ); // future proof by including most symbols without using regex - string host = (p > 0) ? peer_add.substr( 1, p-1 ) : peer_add.substr( 0, colon ); - string port = peer_add.substr( colon + 1, colon2 == string::npos ? string::npos : colon2 - (colon + 1)); - string type = colon2 == string::npos ? "" : end == string::npos ? - peer_add.substr( colon2 + 1 ) : peer_add.substr( colon2 + 1, end - (colon2 + 1) ); - return {std::move(host), std::move(port), std::move(type)}; - } - } // namespace eosio::net_utils \ No newline at end of file