@@ -1317,6 +1317,9 @@ size_t V2Transport::GetMaxBytesToProcess() noexcept
1317
1317
bool V2Transport::ReceivedBytes (Span<const uint8_t >& msg_bytes) noexcept
1318
1318
{
1319
1319
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
+
1320
1323
LOCK (m_recv_mutex);
1321
1324
if (m_recv_state == RecvState::V1) return m_v1_fallback.ReceivedBytes (msg_bytes);
1322
1325
@@ -1327,6 +1330,40 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
1327
1330
while (!msg_bytes.empty ()) {
1328
1331
// Decide how many bytes to copy from msg_bytes to m_recv_buffer.
1329
1332
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
+
1330
1367
// Can't read more than provided input.
1331
1368
max_read = std::min (msg_bytes.size (), max_read);
1332
1369
// Copy data to buffer.
0 commit comments