2424#include < unordered_map>
2525
2626namespace llmq {
27+ namespace {
28+ template <typename T>
29+ bool ReadLimitedVector (CDataStream& stream, std::vector<T>& ret, const size_t max_size, size_t & size)
30+ {
31+ size = ReadCompactSize (stream);
32+ if (size > max_size) {
33+ return false ;
34+ }
35+ ret.clear ();
36+ ret.reserve (size);
37+ while (ret.size () < size) {
38+ ret.emplace_back ();
39+ stream >> ret.back ();
40+ }
41+ return true ;
42+ }
43+ } // namespace
44+
2745void NetSigning::ProcessMessage (CNode& pfrom, const std::string& msg_type, CDataStream& vRecv)
2846{
2947 if (msg_type == NetMsgType::QSIGREC ) {
@@ -45,11 +63,10 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
4563
4664 if (m_sporkman.IsSporkActive (SPORK_21_QUORUM_ALL_CONNECTED ) && msg_type == NetMsgType::QSIGSHARE ) {
4765 std::vector<CSigShare> receivedSigShares;
48- vRecv >> receivedSigShares;
49-
50- if (receivedSigShares.size () > CSigSharesManager::MAX_MSGS_SIG_SHARES ) {
66+ size_t msg_size{0 };
67+ if (!ReadLimitedVector (vRecv, receivedSigShares, CSigSharesManager::MAX_MSGS_SIG_SHARES , msg_size)) {
5168 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 ());
69+ __func__, static_cast < int >(msg_size ), CSigSharesManager::MAX_MSGS_SIG_SHARES , pfrom.GetId ());
5370 BanNode (pfrom.GetId ());
5471 return ;
5572 }
@@ -63,11 +80,11 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
6380
6481 if (msg_type == NetMsgType::QSIGSESANN ) {
6582 std::vector<CSigSesAnn> msgs;
66- vRecv >> msgs ;
67- if (msgs. size () > CSigSharesManager::MAX_MSGS_CNT_QSIGSESANN ) {
83+ size_t msg_size{ 0 } ;
84+ if (! ReadLimitedVector (vRecv, msgs, CSigSharesManager::MAX_MSGS_CNT_QSIGSESANN , msg_size) ) {
6885 LogPrint (BCLog::LLMQ_SIGS , /* Continued */
6986 " 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 ());
87+ __func__, static_cast < int >(msg_size ), CSigSharesManager::MAX_MSGS_CNT_QSIGSESANN , pfrom.GetId ());
7188 BanNode (pfrom.GetId ());
7289 return ;
7390 }
@@ -80,17 +97,18 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
8097 } else if (msg_type == NetMsgType::QSIGSHARESINV || msg_type == NetMsgType::QGETSIGSHARES ) {
8198 std::vector<CSigSharesInv> msgs;
8299 try {
83- vRecv >> msgs;
100+ size_t msg_size{0 };
101+ if (!ReadLimitedVector (vRecv, msgs, CSigSharesManager::MAX_MSGS_CNT_QSIGSHARES , msg_size)) {
102+ LogPrint (BCLog::LLMQ_SIGS , " NetSigning::%s -- too many invs in %s message. cnt=%d, max=%d, node=%d\n " ,
103+ __func__, msg_type, static_cast <int >(msg_size), CSigSharesManager::MAX_MSGS_CNT_QSIGSHARES ,
104+ pfrom.GetId ());
105+ BanNode (pfrom.GetId ());
106+ return ;
107+ }
84108 } catch (const std::ios_base::failure&) {
85109 BanNode (pfrom.GetId ());
86110 throw ;
87111 }
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- }
94112 if (!std::ranges::all_of (msgs, [this , &pfrom, &msg_type](const auto & inv) {
95113 return m_shares_manager->ProcessMessageSigShares (pfrom, inv, msg_type);
96114 })) {
@@ -99,18 +117,13 @@ void NetSigning::ProcessMessage(CNode& pfrom, const std::string& msg_type, CData
99117 }
100118 } else if (msg_type == NetMsgType::QBSIGSHARES ) {
101119 std::vector<CBatchedSigShares> msgs;
102- const size_t msgs_size{ ReadCompactSize (vRecv) };
103- if (msgs_size > MAX_MSGS_TOTAL_BATCHED_SIGS ) {
120+ size_t msg_size{ 0 };
121+ if (! ReadLimitedVector (vRecv, msgs, MAX_MSGS_TOTAL_BATCHED_SIGS , msg_size) ) {
104122 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 ());
123+ __func__, static_cast <int >(msg_size ), MAX_MSGS_TOTAL_BATCHED_SIGS , pfrom.GetId ());
106124 BanNode (pfrom.GetId ());
107125 return ;
108126 }
109- msgs.reserve (msgs_size);
110- while (msgs.size () < msgs_size) {
111- msgs.emplace_back ();
112- vRecv >> msgs.back ();
113- }
114127 const size_t totalSigsCount = std23::ranges::fold_left (msgs, size_t {0 }, [](size_t s, const auto & bs) {
115128 return s + bs.sigShares .size ();
116129 });
0 commit comments