Skip to content

Commit ce347a1

Browse files
committed
fix: bound LLMQ signing vector intake
1 parent 71c74ea commit ce347a1

1 file changed

Lines changed: 50 additions & 39 deletions

File tree

src/llmq/net_signing.cpp

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <llmq/signing_shares.h>
1111
#include <llmq/signing.h>
1212
#include <spork.h>
13-
#include <util/std23.h>
1413

1514
#include <logging.h>
1615
#include <streams.h>
@@ -24,6 +23,43 @@
2423
#include <unordered_map>
2524

2625
namespace llmq {
26+
namespace {
27+
template <typename T>
28+
void ReadLimitedVector(CDataStream& stream, std::vector<T>& ret, const size_t max_size)
29+
{
30+
const size_t size{ReadCompactSize(stream)};
31+
if (size > max_size) {
32+
throw std::ios_base::failure("vector size too large");
33+
}
34+
ret.clear();
35+
ret.reserve(size);
36+
while (ret.size() < size) {
37+
ret.emplace_back();
38+
stream >> ret.back();
39+
}
40+
}
41+
42+
void ReadBatchedSigShares(CDataStream& stream, std::vector<CBatchedSigShares>& ret)
43+
{
44+
const size_t size{ReadCompactSize(stream)};
45+
if (size > MAX_MSGS_TOTAL_BATCHED_SIGS) {
46+
throw std::ios_base::failure("QBSIGSHARES batch count too large");
47+
}
48+
ret.clear();
49+
ret.reserve(size);
50+
51+
size_t total_sigs_count{0};
52+
while (ret.size() < size) {
53+
ret.emplace_back();
54+
stream >> ret.back();
55+
total_sigs_count += ret.back().sigShares.size();
56+
if (total_sigs_count > MAX_MSGS_TOTAL_BATCHED_SIGS) {
57+
throw std::ios_base::failure("QBSIGSHARES sig share count too large");
58+
}
59+
}
60+
}
61+
} // namespace
62+
2763
void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv)
2864
{
2965
if (msg_type == NetMsgType::QSIGREC) {
@@ -45,13 +81,11 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
4581

4682
if (m_sporkman.IsSporkActive(SPORK_21_QUORUM_ALL_CONNECTED) && msg_type == NetMsgType::QSIGSHARE) {
4783
std::vector<CSigShare> receivedSigShares;
48-
vRecv >> receivedSigShares;
49-
50-
if (receivedSigShares.size() > CSigSharesManager::MAX_MSGS_SIG_SHARES) {
51-
LogPrint(BCLog::LLMQ_SIGS, "NetSigning::%s -- too many sigs in QSIGSHARE message. cnt=%d, max=%d, node=%d\n",
52-
__func__, receivedSigShares.size(), CSigSharesManager::MAX_MSGS_SIG_SHARES, pfrom.GetId());
84+
try {
85+
ReadLimitedVector(vRecv, receivedSigShares, CSigSharesManager::MAX_MSGS_SIG_SHARES);
86+
} catch (const std::ios_base::failure&) {
5387
BanNode(pfrom.GetId());
54-
return;
88+
throw;
5589
}
5690

5791
for (const auto& sigShare : receivedSigShares) {
@@ -63,13 +97,11 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
6397

6498
if (msg_type == NetMsgType::QSIGSESANN) {
6599
std::vector<CSigSesAnn> msgs;
66-
vRecv >> msgs;
67-
if (msgs.size() > CSigSharesManager::MAX_MSGS_CNT_QSIGSESANN) {
68-
LogPrint(BCLog::LLMQ_SIGS, /* Continued */
69-
"NetSigning::%s -- too many announcements in QSIGSESANN message. cnt=%d, max=%d, node=%d\n",
70-
__func__, msgs.size(), CSigSharesManager::MAX_MSGS_CNT_QSIGSESANN, pfrom.GetId());
100+
try {
101+
ReadLimitedVector(vRecv, msgs, CSigSharesManager::MAX_MSGS_CNT_QSIGSESANN);
102+
} catch (const std::ios_base::failure&) {
71103
BanNode(pfrom.GetId());
72-
return;
104+
throw;
73105
}
74106
if (!std::ranges::all_of(msgs, [this, &pfrom](const auto& ann) {
75107
return m_shares_manager->ProcessMessageSigSesAnn(pfrom, ann);
@@ -80,17 +112,11 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
80112
} else if (msg_type == NetMsgType::QSIGSHARESINV || msg_type == NetMsgType::QGETSIGSHARES) {
81113
std::vector<CSigSharesInv> msgs;
82114
try {
83-
vRecv >> msgs;
115+
ReadLimitedVector(vRecv, msgs, CSigSharesManager::MAX_MSGS_CNT_QSIGSHARES);
84116
} catch (const std::ios_base::failure&) {
85117
BanNode(pfrom.GetId());
86118
throw;
87119
}
88-
if (msgs.size() > CSigSharesManager::MAX_MSGS_CNT_QSIGSHARES) {
89-
LogPrint(BCLog::LLMQ_SIGS, "NetSigning::%s -- too many invs in %s message. cnt=%d, max=%d, node=%d\n",
90-
__func__, msg_type, msgs.size(), CSigSharesManager::MAX_MSGS_CNT_QSIGSHARES, pfrom.GetId());
91-
BanNode(pfrom.GetId());
92-
return;
93-
}
94120
if (!std::ranges::all_of(msgs, [this, &pfrom, &msg_type](const auto& inv) {
95121
return m_shares_manager->ProcessMessageSigShares(pfrom, inv, msg_type);
96122
})) {
@@ -99,26 +125,11 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
99125
}
100126
} else if (msg_type == NetMsgType::QBSIGSHARES) {
101127
std::vector<CBatchedSigShares> msgs;
102-
const size_t msgs_size{ReadCompactSize(vRecv)};
103-
if (msgs_size > MAX_MSGS_TOTAL_BATCHED_SIGS) {
104-
LogPrint(BCLog::LLMQ_SIGS, "NetSigning::%s -- too many batches in QBSIGSHARES message. cnt=%d, max=%d, node=%d\n",
105-
__func__, static_cast<int>(msgs_size), MAX_MSGS_TOTAL_BATCHED_SIGS, pfrom.GetId());
106-
BanNode(pfrom.GetId());
107-
return;
108-
}
109-
msgs.reserve(msgs_size);
110-
while (msgs.size() < msgs_size) {
111-
msgs.emplace_back();
112-
vRecv >> msgs.back();
113-
}
114-
const size_t totalSigsCount = std23::ranges::fold_left(msgs, size_t{0}, [](size_t s, const auto& bs) {
115-
return s + bs.sigShares.size();
116-
});
117-
if (totalSigsCount > MAX_MSGS_TOTAL_BATCHED_SIGS) {
118-
LogPrint(BCLog::LLMQ_SIGS, "NetSigning::%s -- too many sigs in QBSIGSHARES message. cnt=%d, max=%d, node=%d\n",
119-
__func__, static_cast<int>(totalSigsCount), MAX_MSGS_TOTAL_BATCHED_SIGS, pfrom.GetId());
128+
try {
129+
ReadBatchedSigShares(vRecv, msgs);
130+
} catch (const std::ios_base::failure&) {
120131
BanNode(pfrom.GetId());
121-
return;
132+
throw;
122133
}
123134
if (!std::ranges::all_of(msgs, [this, &pfrom](const auto& bs) {
124135
return m_shares_manager->ProcessMessageBatchedSigShares(pfrom, bs);

0 commit comments

Comments
 (0)