From 47001a394e5a15060db9615f3a90926d99dc60e8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 5 Mar 2023 11:50:11 -0600 Subject: [PATCH] fix: 7f9ef4730 use-after-free in peerMsgs::canRead (#5152) --- libtransmission/peer-msgs.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc index 2504dcba4..d15ada5a3 100644 --- a/libtransmission/peer-msgs.cc +++ b/libtransmission/peer-msgs.cc @@ -1792,15 +1792,15 @@ ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece) } // read - auto& payload = msgs->incoming.payload; + auto& current_payload = msgs->incoming.payload; auto const full_payload_len = *current_message_len - sizeof(uint8_t /*message_type*/); - auto n_left = full_payload_len - std::size(payload); + auto n_left = full_payload_len - std::size(current_payload); while (n_left > 0U && io->read_buffer_size() > 0U) { auto buf = std::array{}; auto const n_this_pass = std::min({ n_left, io->read_buffer_size(), std::size(buf) }); io->read_bytes(std::data(buf), n_this_pass); - payload.add(std::data(buf), n_this_pass); + current_payload.add(std::data(buf), n_this_pass); n_left -= n_this_pass; logtrace(msgs, fmt::format("read {:d} payload bytes; {:d} left to go", n_this_pass, n_left)); } @@ -1810,10 +1810,17 @@ ReadState canRead(tr_peerIo* io, void* vmsgs, size_t* piece) return READ_LATER; } - auto const [read_state, n_piece_bytes_read] = process_peer_message(msgs, *current_message_type, payload); - current_message_type.reset(); + // The incoming message is now complete. Reset the peerMsgs' incoming + // field so it's ready to receive the next message, then process the + // current one with `process_peer_message()`. + current_message_len.reset(); - payload.clear(); + auto const message_type = *current_message_type; + current_message_type.reset(); + auto payload = libtransmission::Buffer{}; + std::swap(payload, current_payload); + + auto const [read_state, n_piece_bytes_read] = process_peer_message(msgs, message_type, payload); *piece = n_piece_bytes_read; return read_state; }