@@ -1317,6 +1317,9 @@ size_t V2Transport::GetMaxBytesToProcess() noexcept
13171317bool V2Transport::ReceivedBytes (Span<const uint8_t >& msg_bytes) noexcept
13181318{
13191319 AssertLockNotHeld (m_recv_mutex);
1320+ /* * How many bytes to allocate in the receive buffer at most above what is received so far. */
1321+ static constexpr size_t MAX_RESERVE_AHEAD = 256 * 1024 ;
1322+
13201323 LOCK (m_recv_mutex);
13211324 if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes (msg_bytes);
13221325
@@ -1327,6 +1330,40 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
13271330 while (!msg_bytes.empty ()) {
13281331 // Decide how many bytes to copy from msg_bytes to m_recv_buffer.
13291332 size_t max_read = GetMaxBytesToProcess ();
1333+
1334+ // Reserve space in the buffer if there is not enough.
1335+ if (m_recv_buffer.size () + std::min (msg_bytes.size (), max_read) > m_recv_buffer.capacity ()) {
1336+ switch (m_recv_state) {
1337+ case RecvState::KEY_MAYBE_V1:
1338+ case RecvState::KEY:
1339+ case RecvState::GARB_GARBTERM:
1340+ // During the initial states (key/garbage), allocate once to fit the maximum (4111
1341+ // bytes).
1342+ m_recv_buffer.reserve (MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
1343+ break ;
1344+ case RecvState::GARBAUTH:
1345+ case RecvState::VERSION:
1346+ case RecvState::APP: {
1347+ // During states where a packet is being received, as much as is expected but never
1348+ // more than MAX_RESERVE_AHEAD bytes in addition to what is received so far.
1349+ // This means attackers that want to cause us to waste allocated memory are limited
1350+ // to MAX_RESERVE_AHEAD above the largest allowed message contents size, and to
1351+ // MAX_RESERVE_AHEAD more than they've actually sent us.
1352+ size_t alloc_add = std::min (max_read, msg_bytes.size () + MAX_RESERVE_AHEAD);
1353+ m_recv_buffer.reserve (m_recv_buffer.size () + alloc_add);
1354+ break ;
1355+ }
1356+ case RecvState::APP_READY:
1357+ // The buffer is empty in this state.
1358+ Assume (m_recv_buffer.empty ());
1359+ break ;
1360+ case RecvState::V1:
1361+ // Should have bailed out above.
1362+ Assume (false );
1363+ break ;
1364+ }
1365+ }
1366+
13301367 // Can't read more than provided input.
13311368 max_read = std::min (msg_bytes.size (), max_read);
13321369 // Copy data to buffer.
0 commit comments