mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-06 14:19:59 -05:00
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
This commit is contained in:
commit
af88094e4f
1 changed files with 58 additions and 63 deletions
|
@ -390,42 +390,36 @@ public:
|
||||||
nOrderPos = -1;
|
nOrderPos = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
template<typename Stream>
|
||||||
|
void Serialize(Stream& s) const
|
||||||
template <typename Stream, typename Operation>
|
{
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
||||||
if (ser_action.ForRead())
|
|
||||||
Init(nullptr);
|
|
||||||
char fSpent = false;
|
char fSpent = false;
|
||||||
|
mapValue_t mapValueCopy = mapValue;
|
||||||
|
|
||||||
if (!ser_action.ForRead())
|
mapValueCopy["fromaccount"] = strFromAccount;
|
||||||
{
|
WriteOrderPos(nOrderPos, mapValueCopy);
|
||||||
mapValue["fromaccount"] = strFromAccount;
|
if (nTimeSmart) {
|
||||||
|
mapValueCopy["timesmart"] = strprintf("%u", nTimeSmart);
|
||||||
WriteOrderPos(nOrderPos, mapValue);
|
|
||||||
|
|
||||||
if (nTimeSmart)
|
|
||||||
mapValue["timesmart"] = strprintf("%u", nTimeSmart);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
READWRITE(*static_cast<CMerkleTx*>(this));
|
s << *static_cast<const CMerkleTx*>(this);
|
||||||
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
|
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
|
||||||
READWRITE(vUnused);
|
s << vUnused << mapValueCopy << vOrderForm << fTimeReceivedIsTxTime << nTimeReceived << fFromMe << fSpent;
|
||||||
READWRITE(mapValue);
|
}
|
||||||
READWRITE(vOrderForm);
|
|
||||||
READWRITE(fTimeReceivedIsTxTime);
|
|
||||||
READWRITE(nTimeReceived);
|
|
||||||
READWRITE(fFromMe);
|
|
||||||
READWRITE(fSpent);
|
|
||||||
|
|
||||||
if (ser_action.ForRead())
|
template<typename Stream>
|
||||||
{
|
void Unserialize(Stream& s)
|
||||||
strFromAccount = mapValue["fromaccount"];
|
{
|
||||||
|
Init(nullptr);
|
||||||
|
char fSpent;
|
||||||
|
|
||||||
ReadOrderPos(nOrderPos, mapValue);
|
s >> *static_cast<CMerkleTx*>(this);
|
||||||
|
std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
|
||||||
|
s >> vUnused >> mapValue >> vOrderForm >> fTimeReceivedIsTxTime >> nTimeReceived >> fFromMe >> fSpent;
|
||||||
|
|
||||||
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
|
strFromAccount = std::move(mapValue["fromaccount"]);
|
||||||
}
|
ReadOrderPos(nOrderPos, mapValue);
|
||||||
|
nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
|
||||||
|
|
||||||
mapValue.erase("fromaccount");
|
mapValue.erase("fromaccount");
|
||||||
mapValue.erase("spent");
|
mapValue.erase("spent");
|
||||||
|
@ -608,48 +602,49 @@ public:
|
||||||
nEntryNo = 0;
|
nEntryNo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
template <typename Stream>
|
||||||
|
void Serialize(Stream& s) const {
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
||||||
int nVersion = s.GetVersion();
|
int nVersion = s.GetVersion();
|
||||||
if (!(s.GetType() & SER_GETHASH))
|
if (!(s.GetType() & SER_GETHASH)) {
|
||||||
READWRITE(nVersion);
|
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
//! Note: strAccount is serialized as part of the key, not here.
|
||||||
|
s << nCreditDebit << nTime << strOtherAccount;
|
||||||
|
|
||||||
READWRITE(LIMITED_STRING(strComment, 65536));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
size_t nSepPos = strComment.find("\0", 0, 1);
|
||||||
if (ser_action.ForRead())
|
mapValue.clear();
|
||||||
{
|
if (std::string::npos != nSepPos) {
|
||||||
mapValue.clear();
|
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
|
||||||
if (std::string::npos != nSepPos)
|
ss >> mapValue;
|
||||||
{
|
_ssExtra = std::vector<char>(ss.begin(), ss.end());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
if (std::string::npos != nSepPos)
|
ReadOrderPos(nOrderPos, mapValue);
|
||||||
|
if (std::string::npos != nSepPos) {
|
||||||
strComment.erase(nSepPos);
|
strComment.erase(nSepPos);
|
||||||
|
}
|
||||||
|
|
||||||
mapValue.erase("n");
|
mapValue.erase("n");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue