Fix the bug Andrey reported. A reference into an array can become invalid if

the array changes size. This happened in the txn metadata code when we had
to thread while handling a node.
This commit is contained in:
JoelKatz
2012-10-20 12:52:25 -07:00
parent 7b8e445456
commit 4b2b75b367
3 changed files with 49 additions and 20 deletions

View File

@@ -6,8 +6,10 @@
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include "Log.h"
TransactionMetaSet::TransactionMetaSet(const uint256& txid, uint32 ledger, const std::vector<unsigned char>& vec) :
mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes)
mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32)
{
Serializer s(vec);
SerializerIterator sit(s);
@@ -29,16 +31,14 @@ bool TransactionMetaSet::isNodeAffected(const uint256& node) const
return false;
}
STObject& TransactionMetaSet::getAffectedNode(const uint256& node, SField::ref type, bool overrideType)
{
assert(&type);
void TransactionMetaSet::setAffectedNode(const uint256& node, SField::ref type)
{ // make sure the node exists and force its type
for (STArray::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
{
if (it->getFieldH256(sfLedgerIndex) == node)
{
if (overrideType)
it->setFName(type);
return *it;
it->setFName(type);
return;
}
}
@@ -47,10 +47,37 @@ STObject& TransactionMetaSet::getAffectedNode(const uint256& node, SField::ref t
assert(obj.getFName() == type);
obj.setFieldH256(sfLedgerIndex, node);
}
STObject& TransactionMetaSet::getAffectedNode(const uint256& node, SField::ref type)
{
assert(&type);
for (STArray::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
{
if (it->getFieldH256(sfLedgerIndex) == node)
return *it;
}
mNodes.push_back(STObject(sfModifiedNode));
STObject& obj = mNodes.back();
assert(obj.getFName() == type);
obj.setFieldH256(sfLedgerIndex, node);
return obj;
}
STObject& TransactionMetaSet::getAffectedNode(const uint256& node)
{
for (STArray::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
{
if (it->getFieldH256(sfLedgerIndex) == node)
return *it;
}
assert(false);
throw std::runtime_error("Affected node not found");
}
const STObject& TransactionMetaSet::peekAffectedNode(const uint256& node) const
{
for (STArray::const_iterator it = mNodes.begin(); it != mNodes.end(); ++it)
@@ -63,7 +90,7 @@ void TransactionMetaSet::init(const uint256& id, uint32 ledger)
{
mTransactionID = id;
mLedger = ledger;
mNodes = STArray(sfAffectedNodes);
mNodes = STArray(sfAffectedNodes, 32);
}
void TransactionMetaSet::swap(TransactionMetaSet& s)