Add a way to limit deserialized string lengths

and use it for most strings being serialized.
This commit is contained in:
Pieter Wuille 2014-08-07 23:00:01 +02:00
parent 003bbd5f76
commit 216e9a4456
4 changed files with 46 additions and 14 deletions

View file

@ -60,9 +60,9 @@ public:
READWRITE(setSubVer); READWRITE(setSubVer);
READWRITE(nPriority); READWRITE(nPriority);
READWRITE(strComment); READWRITE(LIMITED_STRING(strComment, 65536));
READWRITE(strStatusBar); READWRITE(LIMITED_STRING(strStatusBar, 256));
READWRITE(strReserved); READWRITE(LIMITED_STRING(strReserved, 256));
) )
void SetNull(); void SetNull();

View file

@ -3559,7 +3559,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (!vRecv.empty()) if (!vRecv.empty())
vRecv >> addrFrom >> nNonce; vRecv >> addrFrom >> nNonce;
if (!vRecv.empty()) { if (!vRecv.empty()) {
vRecv >> pfrom->strSubVer; vRecv >> LIMITED_STRING(pfrom->strSubVer, 256);
pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer); pfrom->cleanSubVer = SanitizeString(pfrom->strSubVer);
} }
if (!vRecv.empty()) if (!vRecv.empty())
@ -4183,7 +4183,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (fDebug) if (fDebug)
{ {
string strMsg; unsigned char ccode; string strReason; string strMsg; unsigned char ccode; string strReason;
vRecv >> strMsg >> ccode >> strReason; vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, 111);
ostringstream ss; ostringstream ss;
ss << strMsg << " code " << itostr(ccode) << ": " << strReason; ss << strMsg << " code " << itostr(ccode) << ": " << strReason;
@ -4194,10 +4194,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
vRecv >> hash; vRecv >> hash;
ss << ": hash " << hash.ToString(); ss << ": hash " << hash.ToString();
} }
// Truncate to reasonable length and sanitize before printing: LogPrint("net", "Reject %s\n", SanitizeString(ss.str()));
string s = ss.str();
if (s.size() > 111) s.erase(111, string::npos);
LogPrint("net", "Reject %s\n", SanitizeString(s));
} }
} }

View file

@ -336,6 +336,7 @@ I ReadVarInt(Stream& is)
#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) #define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
#define VARINT(obj) REF(WrapVarInt(REF(obj))) #define VARINT(obj) REF(WrapVarInt(REF(obj)))
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))
/** Wrapper for serializing arrays and POD. /** Wrapper for serializing arrays and POD.
*/ */
@ -398,6 +399,40 @@ public:
} }
}; };
template<size_t Limit>
class LimitedString
{
protected:
std::string& string;
public:
LimitedString(std::string& string) : string(string) {}
template<typename Stream>
void Unserialize(Stream& s, int, int=0)
{
size_t size = ReadCompactSize(s);
if (size > Limit) {
throw std::ios_base::failure("String length limit exceeded");
}
string.resize(size);
if (size != 0)
s.read((char*)&string[0], size);
}
template<typename Stream>
void Serialize(Stream& s, int, int=0) const
{
WriteCompactSize(s, string.size());
if (!string.empty())
s.write((char*)&string[0], string.size());
}
unsigned int GetSerializeSize(int, int=0) const
{
return GetSizeOfCompactSize(string.size()) + string.size();
}
};
template<typename I> template<typename I>
CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); } CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }

View file

@ -858,7 +858,7 @@ public:
READWRITE(vchPrivKey); READWRITE(vchPrivKey);
READWRITE(nTimeCreated); READWRITE(nTimeCreated);
READWRITE(nTimeExpires); READWRITE(nTimeExpires);
READWRITE(strComment); READWRITE(LIMITED_STRING(strComment, 65536));
) )
}; };
@ -933,7 +933,7 @@ public:
// Note: strAccount is serialized as part of the key, not here. // Note: strAccount is serialized as part of the key, not here.
READWRITE(nCreditDebit); READWRITE(nCreditDebit);
READWRITE(nTime); READWRITE(nTime);
READWRITE(strOtherAccount); READWRITE(LIMITED_STRING(strOtherAccount, 65536));
if (!fRead) if (!fRead)
{ {
@ -949,7 +949,7 @@ public:
} }
} }
READWRITE(strComment); READWRITE(LIMITED_STRING(strComment, 65536));
size_t nSepPos = strComment.find("\0", 0, 1); size_t nSepPos = strComment.find("\0", 0, 1);
if (fRead) if (fRead)