diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 484d02639..08cc741ee 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -736,6 +736,7 @@ namespace libtorrent // if we're a seed, we don't keep track of piece availability if (t->has_picker()) { + TORRENT_ASSERT(m_have_piece.size() == t->torrent_file().num_pieces()); t->peer_has(m_have_piece, this); bool interesting = false; for (int i = 0; i < int(m_have_piece.size()); ++i) @@ -1540,7 +1541,7 @@ namespace libtorrent #endif return; } - + if (t->valid_metadata()) { if (index >= int(m_have_piece.size())) @@ -2030,8 +2031,13 @@ namespace libtorrent // if we don't have the metedata, we cannot // verify the bitfield size if (t->valid_metadata() - && (bits.size() + 7) / 8 != (m_have_piece.size() + 7) / 8) + && bits.size() != int(m_have_piece.size())) { +#ifndef TORRENT_DISABLE_LOGGING + peer_log(peer_log_alert::incoming_message, "BITFIELD" + , "invalid size: %d expected %d", bits.size() + , int(m_have_piece.size())); +#endif disconnect(errors::invalid_bitfield_size, op_bittorrent, 2); return; } diff --git a/src/torrent.cpp b/src/torrent.cpp index b52333975..e87e8cc1e 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1313,6 +1313,8 @@ namespace libtorrent { if (m_picker) return; + TORRENT_ASSERT(valid_metadata()); + INVARIANT_CHECK; // if we have all pieces we should not have a picker @@ -3417,8 +3419,7 @@ namespace libtorrent continue; #if TORRENT_USE_I2P - char const* top_domain = strrchr(i->hostname.c_str(), '.'); - if (top_domain && strcmp(top_domain, ".i2p") == 0) + if (r.i2pconn && boost::algorithm::ends_with(i->hostname, ".i2p")) { // this is an i2p name, we need to use the sam connection // to do the name lookup @@ -3431,12 +3432,13 @@ namespace libtorrent , boost::bind(&torrent::on_i2p_resolve , shared_from_this(), _1, _2)); } - else { + else + { torrent_state st = get_peer_list_state(); need_peer_list(); - if (m_peer_list->add_i2p_peer (i->hostname.c_str (), peer_info::tracker, 0, &st)) - state_updated (); - peers_erased (st.erased); + if (m_peer_list->add_i2p_peer(i->hostname.c_str (), peer_info::tracker, 0, &st)) + state_updated(); + peers_erased(st.erased); } } else @@ -4593,6 +4595,7 @@ namespace libtorrent { if (has_picker()) { + TORRENT_ASSERT(bits.size() == torrent_file().num_pieces()); torrent_peer* pp = peer->peer_info_struct(); m_picker->inc_refcount(bits, pp); refresh_suggest_pieces(); @@ -4624,6 +4627,7 @@ namespace libtorrent { if (has_picker()) { + TORRENT_ASSERT(bits.size() == torrent_file().num_pieces()); torrent_peer* pp = peer->peer_info_struct(); m_picker->dec_refcount(bits, pp); // TODO: update suggest_piece? diff --git a/test/test_fast_extension.cpp b/test/test_fast_extension.cpp index 2e3bcfba4..c3841d8ec 100644 --- a/test/test_fast_extension.cpp +++ b/test/test_fast_extension.cpp @@ -290,7 +290,7 @@ void send_extension_handshake(tcp::socket& s, entry const& e) std::vector buf; // reserve space for the message header - // uint32: packet-length + // uint32: packet-length // uint8: 20 (extension message) // uint8: 0 (handshake) buf.resize(4 + 1 + 1); @@ -337,7 +337,7 @@ void send_ut_metadata_msg(tcp::socket& s, int ut_metadata_msg, int type, int pie std::vector buf; // reserve space for the message header - // uint32: packet-length + // uint32: packet-length // uint8: 20 (extension message) // uint8: (ut_metadata) buf.resize(4 + 1 + 1); @@ -493,6 +493,46 @@ TORRENT_TEST(reject_fast) print_session_log(*ses); } +TORRENT_TEST(invalid_suggest) +{ + std::cerr << "\n === test suggest ===\n" << std::endl; + + sha1_hash ih; + boost::shared_ptr ses; + io_service ios; + tcp::socket s(ios); + setup_peer(s, ih, ses); + + char recv_buffer[1000]; + do_handshake(s, ih, recv_buffer); + print_session_log(*ses); + send_have_all(s); + print_session_log(*ses); + + // this is an invalid suggest message. We would not expect to receive a + // request for that piece index. + send_suggest_piece(s, -234); + send_unchoke(s); + test_sleep(500); + print_session_log(*ses); + + int len = read_message(s, recv_buffer, sizeof(recv_buffer)); + int idx = -1; + while (len > 0) + { + if (recv_buffer[0] == 6) + { + char* ptr = recv_buffer + 1; + idx = detail::read_int32(ptr); + break; + } + len = read_message(s, recv_buffer, sizeof(recv_buffer)); + } + TEST_CHECK(idx != -234); + TEST_CHECK(idx != -1); + s.close(); +} + TORRENT_TEST(reject_suggest) { std::cerr << "\n === test suggest ===\n" << std::endl;