Skip to content

Commit af88094

Browse files
committed
Merge #12658: Sanitize some wallet serialization
42343c7 Split up and sanitize CAccountingEntry serialization (Pieter Wuille) 029ecac Split up and sanitize CWalletTx serialization (Pieter Wuille) Pull request description: This is a small subset of changes taken from #10785, fixing a few of the craziest constness violations in the serialization code. `CWalletTx` currently serializes some of its fields by embedding them in a key-value `mapValue`, which is modified (and then fixed up) even from the `Serialize` method (for which `mapValue` is const). `CAccountingEntry` goes even further in that it stores such a map by appending it into `strComment` after a null char, which is again later fixed up again. Fix this by splitting the serialization and deserialization code, and making the serialization act on a copy of `mapValue` / `strComment`. Tree-SHA512: 487e04996dea6aba5b9b8bdaf2c4e680808f111a15afc557b8d078e14b01e4f40f8ef27588869be62f9a87052117c17e0a0c26c59150f83472a9076936af035e
2 parents 702e8b7 + 42343c7 commit af88094

File tree

1 file changed

+58
-63
lines changed

1 file changed

+58
-63
lines changed

src/wallet/wallet.h

Lines changed: 58 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -390,42 +390,36 @@ class CWalletTx : public CMerkleTx
390390
nOrderPos = -1;
391391
}
392392

393-
ADD_SERIALIZE_METHODS;
394-
395-
template <typename Stream, typename Operation>
396-
inline void SerializationOp(Stream& s, Operation ser_action) {
397-
if (ser_action.ForRead())
398-
Init(nullptr);
393+
template<typename Stream>
394+
void Serialize(Stream& s) const
395+
{
399396
char fSpent = false;
397+
mapValue_t mapValueCopy = mapValue;
400398

401-
if (!ser_action.ForRead())
402-
{
403-
mapValue["fromaccount"] = strFromAccount;
404-
405-
WriteOrderPos(nOrderPos, mapValue);
406-
407-
if (nTimeSmart)
408-
mapValue["timesmart"] = strprintf("%u", nTimeSmart);
399+
mapValueCopy["fromaccount"] = strFromAccount;
400+
WriteOrderPos(nOrderPos, mapValueCopy);
401+
if (nTimeSmart) {
402+
mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
409403
}
410404

411-
READWRITE(*static_cast<CMerkleTx*>(this));
405+
s << *static_cast<const CMerkleTx*>(this);
412406
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
413-
READWRITE(vUnused);
414-
READWRITE(mapValue);
415-
READWRITE(vOrderForm);
416-
READWRITE(fTimeReceivedIsTxTime);
417-
READWRITE(nTimeReceived);
418-
READWRITE(fFromMe);
419-
READWRITE(fSpent);
420-
421-
if (ser_action.ForRead())
422-
{
423-
strFromAccount = mapValue["fromaccount"];
407+
s << vUnused << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << fSpent;
408+
}
424409

425-
ReadOrderPos(nOrderPos, mapValue);
410+
template<typename Stream>
411+
void Unserialize(Stream& s)
412+
{
413+
Init(nullptr);
414+
char fSpent;
426415

427-
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
428-
}
416+
s >> *static_cast<CMerkleTx*>(this);
417+
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
418+
s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent;
419+
420+
strFromAccount = std::move(mapValue["fromaccount"]);
421+
ReadOrderPos(nOrderPos, mapValue);
422+
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
429423

430424
mapValue.erase("fromaccount");
431425
mapValue.erase("spent");
@@ -608,48 +602,49 @@ class CAccountingEntry
608602
nEntryNo = 0;
609603
}
610604

611-
ADD_SERIALIZE_METHODS;
612-
613-
template <typename Stream, typename Operation>
614-
inline void SerializationOp(Stream& s, Operation ser_action) {
605+
template <typename Stream>
606+
void Serialize(Stream& s) const {
615607
int nVersion = s.GetVersion();
616-
if (!(s.GetType() & SER_GETHASH))
617-
READWRITE(nVersion);
608+
if (!(s.GetType() & SER_GETHASH)) {
609+
s << nVersion;
610+
}
618611
//! Note: strAccount is serialized as part of the key, not here.
619-
READWRITE(nCreditDebit);
620-
READWRITE(nTime);
621-
READWRITE(LIMITED_STRING(strOtherAccount, 65536));
622-
623-
if (!ser_action.ForRead())
624-
{
625-
WriteOrderPos(nOrderPos, mapValue);
626-
627-
if (!(mapValue.empty() && _ssExtra.empty()))
628-
{
629-
CDataStream ss(s.GetType(), s.GetVersion());
630-
ss.insert(ss.begin(), '\0');
631-
ss << mapValue;
632-
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
633-
strComment.append(ss.str());
634-
}
612+
s << nCreditDebit << nTime << strOtherAccount;
613+
614+
mapValue_t mapValueCopy = mapValue;
615+
WriteOrderPos(nOrderPos, mapValueCopy);
616+
617+
std::string strCommentCopy = strComment;
618+
if (!mapValueCopy.empty() || !_ssExtra.empty()) {
619+
CDataStream ss(s.GetType(), s.GetVersion());
620+
ss.insert(ss.begin(), '\0');
621+
ss << mapValueCopy;
622+
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
623+
strCommentCopy.append(ss.str());
635624
}
625+
s << strCommentCopy;
626+
}
636627

637-
READWRITE(LIMITED_STRING(strComment, 65536));
628+
template <typename Stream>
629+
void Unserialize(Stream& s) {
630+
int nVersion = s.GetVersion();
631+
if (!(s.GetType() & SER_GETHASH)) {
632+
s >> nVersion;
633+
}
634+
//! Note: strAccount is serialized as part of the key, not here.
635+
s >> nCreditDebit >> nTime >> LIMITED_STRING(strOtherAccount, 65536) >> LIMITED_STRING(strComment, 65536);
638636

639637
size_t nSepPos = strComment.find("\0", 0, 1);
640-
if (ser_action.ForRead())
641-
{
642-
mapValue.clear();
643-
if (std::string::npos != nSepPos)
644-
{
645-
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
646-
ss >> mapValue;
647-
_ssExtra = std::vector<char>(ss.begin(), ss.end());
648-
}
649-
ReadOrderPos(nOrderPos, mapValue);
638+
mapValue.clear();
639+
if (std::string::npos != nSepPos) {
640+
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
641+
ss >> mapValue;
642+
_ssExtra = std::vector<char>(ss.begin(), ss.end());
650643
}
651-
if (std::string::npos != nSepPos)
644+
ReadOrderPos(nOrderPos, mapValue);
645+
if (std::string::npos != nSepPos) {
652646
strComment.erase(nSepPos);
647+
}
653648

654649
mapValue.erase("n");
655650
}

0 commit comments

Comments
 (0)