diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 117ef3d68..99a51cbc5 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -2515,6 +2515,14 @@ namespace libtorrent } received_bytes(0, consumed); + // don't accept packets larger than 1 MB with a 1KB allowance for headers + if (!m_recv_buffer.crypto_packet_finished() + && m_recv_buffer.crypto_packet_size() > 1025 * 1024) + { + disconnect(errors::packet_too_large, op_encryption, 2); + return; + } + int sub_transferred = 0; while (bytes_transferred > 0 && ((sub_transferred = int(m_recv_buffer.advance_pos(int(bytes_transferred)))) > 0)) diff --git a/src/pe_crypto.cpp b/src/pe_crypto.cpp index 5c3af2b4d..86ffdf987 100644 --- a/src/pe_crypto.cpp +++ b/src/pe_crypto.cpp @@ -122,7 +122,7 @@ namespace libtorrent bufs = TORRENT_ALLOCA(mutable_buffer, iovec.size()); need_destruct = true; num_bufs = 0; - for (int i = 0; to_process > 0; ++i) + for (int i = 0; to_process > 0 && i < iovec.size(); ++i) { ++num_bufs; int const size = buffer_size(iovec[i]); @@ -147,16 +147,19 @@ namespace libtorrent int next_barrier = 0; aux::array_view out_iovec; - bool process_barrier = num_bufs == 0; - if (!process_barrier) + if (num_bufs != 0) { std::tie(next_barrier, out_iovec) = m_send_barriers.front().enc_handler->encrypt({bufs, num_bufs}); - process_barrier = (next_barrier != 0); } - if (process_barrier) + + if (m_send_barriers.front().next != INT_MAX) { - if (m_send_barriers.front().next != INT_MAX) + // to_process holds the difference between the size of the buffers + // and the bytes left to the next barrier + // if it's zero then pop the barrier + // otherwise update the number of bytes remaining to the next barrier + if (to_process == 0) { if (m_send_barriers.size() == 1) { @@ -165,21 +168,25 @@ namespace libtorrent } m_send_barriers.pop_front(); } + else + { + m_send_barriers.front().next = to_process; + } + } #if TORRENT_USE_ASSERTS - if (next_barrier != INT_MAX) - { - int payload = 0; - for (int i = 0; i < num_bufs; ++i) - payload += int(buffer_size(bufs[i])); + if (next_barrier != INT_MAX && next_barrier != 0) + { + int payload = 0; + for (int i = 0; i < num_bufs; ++i) + payload += int(buffer_size(bufs[i])); - int overhead = 0; - for (auto buf : out_iovec) - overhead += int(buffer_size(buf)); - TORRENT_ASSERT(overhead + payload == next_barrier); - } -#endif + int overhead = 0; + for (auto buf : out_iovec) + overhead += int(buffer_size(buf)); + TORRENT_ASSERT(overhead + payload == next_barrier); } +#endif if (need_destruct) { for (int i = 0; i < num_bufs; ++i) diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 322e1b699..99621c60f 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -5501,7 +5501,9 @@ namespace libtorrent if (m_send_barrier == 0) { std::vector vec; - m_send_buffer.build_mutable_iovec(m_send_buffer.size(), vec); + // limit outgoing crypto messages to 1MB + int const send_bytes = (std::min)(m_send_buffer.size(), 1024*1024); + m_send_buffer.build_mutable_iovec(send_bytes, vec); int next_barrier; aux::array_view inject_vec; std::tie(next_barrier, inject_vec) = hit_send_barrier(vec);