fix exit condition when parsing nodes (#1046)

fix exit condition when parsing nodes
This commit is contained in:
Steven Siloti 2016-08-31 21:49:21 -07:00 committed by Arvid Norberg
parent bf0008933a
commit 29e6cbbdae
5 changed files with 105 additions and 5 deletions

View File

@ -206,9 +206,9 @@ public:
dht_observer* observer() const { return m_observer; }
udp protocol() { return m_protocol.protocol; }
char const* protocol_family_name() { return m_protocol.family_name; }
char const* protocol_nodes_key() { return m_protocol.nodes_key; }
udp protocol() const { return m_protocol.protocol; }
char const* protocol_family_name() const { return m_protocol.family_name; }
char const* protocol_nodes_key() const { return m_protocol.nodes_key; }
bool native_address(udp::endpoint ep) const
{ return ep.protocol().family() == m_protocol.protocol.family(); }

View File

@ -56,6 +56,18 @@ namespace libtorrent
namespace detail
{
template <class Proto>
size_t address_size(Proto p)
{
TORRENT_UNUSED(p);
#if TORRENT_USE_IPV6
if (p == Proto::v6())
return address_v6::bytes_type().size();
else
#endif
return address_v4::bytes_type().size();
}
template<class OutIt>
void write_address(address const& a, OutIt& out)
{

View File

@ -621,7 +621,7 @@ struct ping_observer : observer
char const* nodes = n.string_ptr();
char const* end = nodes + n.string_length();
while (end - nodes >= 26)
while (end - nodes >= 20 + detail::address_size(protocol) + 2)
{
node_id id;
std::copy(nodes, nodes + 20, id.begin());

View File

@ -52,6 +52,7 @@ using namespace std::placeholders;
namespace libtorrent { namespace dht
{
using detail::address_size;
using detail::read_v4_endpoint;
#if TORRENT_USE_IPV6
using detail::read_v6_endpoint;
@ -608,7 +609,7 @@ void traversal_observer::reply(msg const& m)
char const* nodes = n.string_ptr();
char const* end = nodes + n.string_length();
while (end - nodes >= 26)
while (end - nodes >= 20 + address_size(protocol) + 2)
{
node_id id;
std::copy(nodes, nodes + 20, id.begin());

View File

@ -1643,6 +1643,93 @@ TORRENT_TEST(bootstrap_v6)
}
#endif
// test that the node ignores a nodes entry which is too short
void test_short_nodes(address(&rand_addr)())
{
dht_test_setup t(udp::endpoint(rand_addr(), 20));
bdecode_node response;
bool ret;
dht::key_desc_t const find_node_desc[] = {
{ "y", bdecode_node::string_t, 1, 0 },
{ "t", bdecode_node::string_t, 2, 0 },
{ "q", bdecode_node::string_t, 9, 0 },
{ "a", bdecode_node::dict_t, 0, key_desc_t::parse_children },
{ "id", bdecode_node::string_t, 20, 0 },
{ "target", bdecode_node::string_t, 20, key_desc_t::optional },
{ "info_hash", bdecode_node::string_t, 20, key_desc_t::optional | key_desc_t::last_child },
};
bdecode_node find_node_keys[7];
// bootstrap
g_sent_packets.clear();
udp::endpoint initial_node(rand_addr(), 1234);
std::vector<udp::endpoint> nodesv;
nodesv.push_back(initial_node);
t.dht_node.bootstrap(nodesv, std::bind(&nop_node));
TEST_EQUAL(g_sent_packets.size(), 1);
if (g_sent_packets.empty()) return;
TEST_EQUAL(g_sent_packets.front().first, initial_node);
lazy_from_entry(g_sent_packets.front().second, response);
ret = verify_message(response, find_node_desc, find_node_keys, t.error_string
, sizeof(t.error_string));
if (ret)
{
TEST_EQUAL(find_node_keys[0].string_value(), "q");
TEST_CHECK(find_node_keys[2].string_value() == "find_node"
|| find_node_keys[2].string_value() == "get_peers");
if (find_node_keys[0].string_value() != "q"
|| (find_node_keys[2].string_value() != "find_node"
&& find_node_keys[2].string_value() != "get_peers")) return;
}
else
{
std::fprintf(stderr, " invalid find_node request: %s\n", print_entry(response).c_str());
TEST_ERROR(t.error_string);
return;
}
udp::endpoint found_node(rand_addr(), 2235);
nodes_t nodes;
nodes.push_back(found_node);
g_sent_packets.clear();
msg_args args;
// chop one byte off of the nodes string
if (initial_node.address().is_v4())
{
args.nodes(nodes);
args.a["nodes"] = args.a["nodes"].string().substr(1);
}
else
{
args.nodes6(nodes);
args.a["nodes6"] = args.a["nodes6"].string().substr(1);
}
send_dht_response(t.dht_node, response, initial_node, args);
TEST_EQUAL(g_sent_packets.size(), 0);
}
TORRENT_TEST(short_nodes_v4)
{
test_short_nodes(rand_v4);
}
#if TORRENT_USE_IPV6
TORRENT_TEST(short_nodes_v6)
{
if (supports_ipv6())
test_short_nodes(rand_v6);
}
#endif
void test_get_peers(address(&rand_addr)())
{
dht_test_setup t(udp::endpoint(rand_addr(), 20));