@@ -41,38 +41,48 @@ namespace detail {
4141 }
4242
4343 // / @return host, port, remainder
44- inline std::tuple<std::string, std::string, std::string> split_host_port_remainder (const std::string& peer_add) {
44+ inline std::tuple<std::string, std::string, std::string> split_host_port_remainder (const std::string& peer_add, bool should_throw ) {
4545 using std::string;
4646 // host:port[:trx|:blk][:<rate>]
4747 if (peer_add.empty ()) return {};
4848
49- string::size_type p = peer_add[0 ] == ' [' ? peer_add.find (' ]' ) : 0 ;
50- if (p == 0 ) {
51- if ( auto colon_count = std::count (peer_add.begin (), peer_add.end (), ' :' ); colon_count >= 7 ) {
52- EOS_ASSERT ( colon_count <= 2 , chain::plugin_config_exception,
53- " Invalid address specification ${a}; IPv6 addresses must be enclosed in square brackets." , (" a" , peer_add));
49+ auto colon_count = std::count (peer_add.begin (), peer_add.end (), ' :' );
50+ string::size_type end_bracket = 0 ;
51+ if (peer_add[0 ] == ' [' ) {
52+ end_bracket = peer_add.find (' ]' );
53+ if (end_bracket == string::npos) {
54+ EOS_ASSERT (!should_throw, chain::plugin_config_exception,
55+ " Invalid address specification ${a}, IPv6 no closing square bracket" , (" a" , peer_add) );
56+ return {};
5457 }
58+ } else if (colon_count >= 7 ) {
59+ EOS_ASSERT (!should_throw, chain::plugin_config_exception,
60+ " Invalid address specification ${a}; IPv6 addresses must be enclosed in square brackets." , (" a" , peer_add));
61+ return {};
62+
5563 }
56- string::size_type colon = p != string::npos ? peer_add.find (' :' , p) : string::npos ;
64+ string::size_type colon = peer_add.find (' :' , end_bracket+ 1 ) ;
5765 if (colon == string::npos || colon == 0 ) {
5866 return {};
5967 }
6068 string::size_type colon2 = peer_add.find (' :' , colon + 1 );
61- string host = (p > 0 ) ? peer_add.substr ( 0 , p +1 ) : peer_add.substr ( 0 , colon );
69+ string host = (end_bracket > 0 ) ? peer_add.substr ( 0 , end_bracket +1 ) : peer_add.substr ( 0 , colon );
6270 string port = peer_add.substr ( colon + 1 , colon2 == string::npos ? string::npos : colon2 - (colon + 1 ));
6371 string remainder = colon2 == string::npos ? " " : peer_add.substr ( colon2 + 1 );
6472 return {std::move (host), std::move (port), std::move (remainder)};
6573 }
6674
6775} // namespace detail
6876
69- // / @return host, port, type
77+ // / @return host, port, type. returns empty on invalid peer_add, does not throw
7078 inline std::tuple<std::string, std::string, std::string> split_host_port_type (const std::string& peer_add) {
79+
7180 using std::string;
7281 // host:port[:trx|:blk][:<rate>] // rate is discarded
7382 if (peer_add.empty ()) return {};
7483
75- auto [host, port, remainder] = detail::split_host_port_remainder (peer_add);
84+ constexpr bool should_throw = false ;
85+ auto [host, port, remainder] = detail::split_host_port_remainder (peer_add, should_throw);
7686 if (host.empty ()) return {};
7787
7888 string::size_type end = remainder.find_first_of ( " :+=.,<>!$%^&(*)|-#@\t " ); // future proof by including most symbols without using regex
@@ -82,9 +92,10 @@ namespace detail {
8292 }
8393
8494 // / @return listen address, type [trx|blk], and block sync rate limit (in bytes/sec) of address string
95+ // / @throws chain::plugin_config_exception on invalid address
8596 inline std::tuple<std::string, size_t > parse_listen_address ( const std::string& address ) {
86-
87- auto [host, port, remainder] = detail::split_host_port_remainder (address);
97+ constexpr bool should_throw = true ;
98+ auto [host, port, remainder] = detail::split_host_port_remainder (address, should_throw );
8899 auto listen_addr = host + " :" + port;
89100 auto limit = remainder;
90101 auto last_colon_location = remainder.rfind (' :' );
@@ -96,24 +107,4 @@ namespace detail {
96107 return {std::move (listen_addr), block_sync_rate_limit};
97108 }
98109
99- inline std::tuple<std::string, std::string, std::string> split_host_xport_type (const std::string& peer_add) {
100- using std::string;
101- // host:port:[<trx>|<blk>]
102- if (peer_add.empty ()) return {};
103-
104- string::size_type p = peer_add[0 ] == ' [' ? peer_add.find (' ]' ) : 0 ;
105- string::size_type colon = p != string::npos ? peer_add.find (' :' , p) : string::npos;
106- if (colon == string::npos || colon == 0 ) {
107- return {};
108- }
109- string::size_type colon2 = peer_add.find (' :' , colon + 1 );
110- string::size_type end = colon2 == string::npos
111- ? string::npos : peer_add.find_first_of ( " :+=.,<>!$%^&(*)|-#@\t " , colon2 + 1 ); // future proof by including most symbols without using regex
112- string host = (p > 0 ) ? peer_add.substr ( 1 , p-1 ) : peer_add.substr ( 0 , colon );
113- string port = peer_add.substr ( colon + 1 , colon2 == string::npos ? string::npos : colon2 - (colon + 1 ));
114- string type = colon2 == string::npos ? " " : end == string::npos ?
115- peer_add.substr ( colon2 + 1 ) : peer_add.substr ( colon2 + 1 , end - (colon2 + 1 ) );
116- return {std::move (host), std::move (port), std::move (type)};
117- }
118-
119110} // namespace eosio::net_utils
0 commit comments