From 98655aed4dd822f58024644a3d96582b7e8f3131 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 29 Sep 2012 01:30:17 -0700 Subject: [PATCH] Correctly check validity for type during setType. --- src/SerializedLedger.cpp | 6 ++-- src/SerializedObject.cpp | 67 ++++++++++++++++++++--------------- src/SerializedObject.h | 3 +- src/SerializedTransaction.cpp | 7 ++-- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index b2cd4f95ce..f96e96e2f9 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -14,7 +14,8 @@ SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type"); mType = mFormat->t_type; - setType(mFormat->elements); + if (!setType(mFormat->elements)) + throw std::runtime_error("ledger entry not valid for type"); } SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& index) @@ -28,7 +29,8 @@ SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type"); mType = mFormat->t_type; - setType(mFormat->elements); + if (!setType(mFormat->elements)) + throw std::runtime_error("ledger entry not valid for type"); } SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type) : STObject(sfLedgerEntry), mType(type) diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 9cd320e06f..c810c0de4d 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -130,46 +130,54 @@ void STObject::set(SOElement::ptr elem) } } -bool STObject::compare(const SerializedType& f1, const SerializedType& f2) +bool STObject::setType(SOElement::ptrList t) { - BOOST_FOREACH(SOElement::ptr elem, mType) - { - if (elem->e_field == f1.getFName()) // element one comes first - return true; - if (elem->e_field == f2.getFName()) // element two comes first - return false; - } - assert(false); - return false; -} + boost::ptr_vector newData; + bool valid = true; -void STObject::setType(SOElement::ptrList t) -{ mType.empty(); while (t->flags != SOE_END) - mType.push_back(t++); + { + bool match = false; + for (boost::ptr_vector::iterator it = mData.begin(); it != mData.end(); ++it) + if (it->getFName() == t->e_field) + { + match = true; + newData.push_back(mData.release(it).release()); + break; + } - std::sort(mData.begin(), mData.end(), boost::bind(&STObject::compare, this, _1, _2)); + if (!match) + { + if (t->flags != SOE_OPTIONAL) + { + Log(lsTRACE) << "setType !valid missing"; + valid = false; + } + newData.push_back(makeNonPresentObject(t->e_field)); + } + + mType.push_back(t++); + } + if (mData.size() != 0) + { + Log(lsTRACE) << "setType !valid leftover"; + valid = false; + } + mData.swap(newData); + return valid; } bool STObject::isValidForType() { + boost::ptr_vector::iterator it = mData.begin(); BOOST_FOREACH(SOElement::ptr elem, mType) - { // are any required elemnents missing - if ((elem->flags == SOE_REQUIRED) && (getPField(elem->e_field) == NULL)) - { - Log(lsWARNING) << getName() << " missing required element " << elem->e_field.fieldName; + { + if (it == mData.end()) return false; - } - } - - BOOST_FOREACH(const SerializedType& elem, mData) - { // are any non-permitted elements present - if (!isFieldAllowed(elem.getFName())) - { - Log(lsWARNING) << getName() << " has non-permitted element " << elem.getName(); + if (elem->e_field != it->getFName()) return false; - } + ++it; } return true; @@ -282,7 +290,8 @@ std::string STObject::getText() const bool STObject::isEquivalent(const SerializedType& t) const { const STObject* v = dynamic_cast(&t); - if (!v) return false; + if (!v) + return false; boost::ptr_vector::const_iterator it1 = mData.begin(), end1 = mData.end(); boost::ptr_vector::const_iterator it2 = v->mData.begin(), end2 = v->mData.end(); while ((it1 != end1) && (it2 != end2)) diff --git a/src/SerializedObject.h b/src/SerializedObject.h index ee66681ee4..98ffc8407e 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -28,7 +28,6 @@ protected: std::vector mType; STObject* duplicate() const { return new STObject(*this); } - bool compare(const SerializedType& f1, const SerializedType& f2); public: STObject() { ; } @@ -45,7 +44,7 @@ public: static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name); - void setType(SOElement::ptrList); + bool setType(SOElement::ptrList); bool isValidForType(); bool isFieldAllowed(SField::ref); diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 5d1bdc6fe2..1fe5109ce6 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -30,11 +30,10 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit) : STObject mFormat = getTxnFormat(mType); if (!mFormat) - throw std::runtime_error("invalid transction type"); - setType(mFormat->elements); - if (!isValidForType()) + throw std::runtime_error("invalid transaction type"); + if (!setType(mFormat->elements)) { - Log(lsDEBUG) << "Transaction not valid for type " << getJson(0); + assert(false); throw std::runtime_error("transaction not valid"); } }