Fix memory DoS
This commit is contained in:
40
src/main.cpp
40
src/main.cpp
@@ -7320,6 +7320,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
const uint256* best_block{nullptr};
|
||||||
|
|
||||||
std::vector<CInv> vToFetch;
|
std::vector<CInv> vToFetch;
|
||||||
|
|
||||||
@@ -7339,35 +7341,31 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if (inv.type == MSG_BLOCK) {
|
if (inv.type == MSG_BLOCK) {
|
||||||
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
|
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
|
||||||
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
|
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
|
||||||
// First request the headers preceding the announced block. In the normal fully-synced
|
// Headers-first is the primary method of announcement on
|
||||||
// case where a new block is announced that succeeds the current tip (no reorganization),
|
// the network. If a node fell back to sending blocks by inv,
|
||||||
// there are no such headers.
|
// it's probably for a re-org. The final block hash
|
||||||
// Secondly, and only when we are close to being synced, we request the announced block directly,
|
// provided should be the highest, so send a getheaders and
|
||||||
// to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
|
// then fetch the blocks we need to catch up.
|
||||||
// time the block arrives, the header chain leading up to it is already validated. Not
|
best_block = &inv.hash;
|
||||||
// doing this will result in the received block being rejected as an orphan in case it is
|
|
||||||
// not a direct successor.
|
|
||||||
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
|
|
||||||
CNodeState *nodestate = State(pfrom->GetId());
|
|
||||||
if (chainActive.Tip()->GetBlockTime() > GetTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 &&
|
|
||||||
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
|
||||||
vToFetch.push_back(inv);
|
|
||||||
// Mark block as in flight already, even though the actual "getdata" message only goes out
|
|
||||||
// later (within the same cs_main lock, though).
|
|
||||||
MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
|
|
||||||
}
|
|
||||||
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->GetHeight(), inv.hash.ToString(), pfrom->id);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
pfrom->AddKnownWTxId(WTxId(inv.hash, inv.hashAux));
|
||||||
|
if (fBlocksOnly)
|
||||||
|
LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id);
|
||||||
|
else if (!fAlreadyHave && !IsInitialBlockDownload(chainparams.GetConsensus()))
|
||||||
|
pfrom->AskFor(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfrom->nSendSize > (SendBufferSize() * 2)) {
|
if (pfrom->nSendSize > (SendBufferSize() * 2)) {
|
||||||
Misbehaving(pfrom->GetId(), 50);
|
Misbehaving(pfrom->GetId(), 50);
|
||||||
return error("send buffer size() = %u", pfrom->nSendSize);
|
return error("send buffer size() = %u", pfrom->nSendSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vToFetch.empty())
|
if (best_block != nullptr) {
|
||||||
pfrom->PushMessage(NetMsgType::GETDATA, vToFetch);
|
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), *best_block);
|
||||||
|
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->GetHeight(), best_block->ToString(), pfrom->id);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (strCommand == NetMsgType::GETDATA) {
|
} else if (strCommand == NetMsgType::GETDATA) {
|
||||||
vector<CInv> vInv;
|
vector<CInv> vInv;
|
||||||
vRecv >> vInv;
|
vRecv >> vInv;
|
||||||
|
|||||||
Reference in New Issue
Block a user