diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-03-13 18:26:45 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-03-13 18:39:55 +0100 |
commit | af88094e4f715ae2dc71d8868b3c734525bcc274 (patch) | |
tree | 517fdd58f1f92fad7d3be2aa9bf6142445d23209 | |
parent | 702e8b70bd870f506ce8157e58b77cb7d0a0f98d (diff) | |
parent | 42343c748c2bca8ba9b888d949088dbfd1f142b4 (diff) |
Merge #12658: Sanitize some wallet serialization
42343c748 Split up and sanitize CAccountingEntry serialization (Pieter Wuille)
029ecac1b 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
-rw-r--r-- | src/wallet/wallet.h | 121 |
1 files changed, 58 insertions, 63 deletions
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 3e2d1794d8..0f29bff1ff 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -390,42 +390,36 @@ public: nOrderPos = -1; } - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action) { - if (ser_action.ForRead()) - Init(nullptr); + template<typename Stream> + void Serialize(Stream& s) const + { char fSpent = false; + mapValue_t mapValueCopy = mapValue; - if (!ser_action.ForRead()) - { - mapValue["fromaccount"] = strFromAccount; - - WriteOrderPos(nOrderPos, mapValue); - - if (nTimeSmart) - mapValue["timesmart"] = strprintf("%u", nTimeSmart); + mapValueCopy["fromaccount"] = strFromAccount; + WriteOrderPos(nOrderPos, mapValueCopy); + if (nTimeSmart) { + mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart); } - READWRITE(*static_cast<CMerkleTx*>(this)); + s << *static_cast<const CMerkleTx*>(this); std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev - READWRITE(vUnused); - READWRITE(mapValue); - READWRITE(vOrderForm); - READWRITE(fTimeReceivedIsTxTime); - READWRITE(nTimeReceived); - READWRITE(fFromMe); - READWRITE(fSpent); - - if (ser_action.ForRead()) - { - strFromAccount = mapValue["fromaccount"]; + s << vUnused << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << fSpent; + } - ReadOrderPos(nOrderPos, mapValue); + template<typename Stream> + void Unserialize(Stream& s) + { + Init(nullptr); + char fSpent; - nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0; - } + s >> *static_cast<CMerkleTx*>(this); + std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev + s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent; + + strFromAccount = std::move(mapValue["fromaccount"]); + ReadOrderPos(nOrderPos, mapValue); + nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0; mapValue.erase("fromaccount"); mapValue.erase("spent"); @@ -608,48 +602,49 @@ public: nEntryNo = 0; } - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action) { + template <typename Stream> + void Serialize(Stream& s) const { int nVersion = s.GetVersion(); - if (!(s.GetType() & SER_GETHASH)) - READWRITE(nVersion); + if (!(s.GetType() & SER_GETHASH)) { + s << nVersion; + } //! Note: strAccount is serialized as part of the key, not here. - READWRITE(nCreditDebit); - READWRITE(nTime); - READWRITE(LIMITED_STRING(strOtherAccount, 65536)); - - if (!ser_action.ForRead()) - { - WriteOrderPos(nOrderPos, mapValue); - - if (!(mapValue.empty() && _ssExtra.empty())) - { - CDataStream ss(s.GetType(), s.GetVersion()); - ss.insert(ss.begin(), '\0'); - ss << mapValue; - ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); - strComment.append(ss.str()); - } + s << nCreditDebit << nTime << strOtherAccount; + + mapValue_t mapValueCopy = mapValue; + WriteOrderPos(nOrderPos, mapValueCopy); + + std::string strCommentCopy = strComment; + if (!mapValueCopy.empty() || !_ssExtra.empty()) { + CDataStream ss(s.GetType(), s.GetVersion()); + ss.insert(ss.begin(), '\0'); + ss << mapValueCopy; + ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end()); + strCommentCopy.append(ss.str()); } + s << strCommentCopy; + } - READWRITE(LIMITED_STRING(strComment, 65536)); + template <typename Stream> + void Unserialize(Stream& s) { + int nVersion = s.GetVersion(); + if (!(s.GetType() & SER_GETHASH)) { + s >> nVersion; + } + //! Note: strAccount is serialized as part of the key, not here. + s >> nCreditDebit >> nTime >> LIMITED_STRING(strOtherAccount, 65536) >> LIMITED_STRING(strComment, 65536); size_t nSepPos = strComment.find("\0", 0, 1); - if (ser_action.ForRead()) - { - mapValue.clear(); - if (std::string::npos != nSepPos) - { - CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion()); - ss >> mapValue; - _ssExtra = std::vector<char>(ss.begin(), ss.end()); - } - ReadOrderPos(nOrderPos, mapValue); + mapValue.clear(); + if (std::string::npos != nSepPos) { + CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion()); + ss >> mapValue; + _ssExtra = std::vector<char>(ss.begin(), ss.end()); } - if (std::string::npos != nSepPos) + ReadOrderPos(nOrderPos, mapValue); + if (std::string::npos != nSepPos) { strComment.erase(nSepPos); + } mapValue.erase("n"); } |