diff --git a/Builds/rpm/rippled.spec b/Builds/rpm/rippled.spec index 00afa5ddaa8..424aa943893 100644 --- a/Builds/rpm/rippled.spec +++ b/Builds/rpm/rippled.spec @@ -1,5 +1,5 @@ Name: rippled -Version: 0.25.2-rc1 +Version: 0.25.2 Release: 1%{?dist} Summary: Ripple peer-to-peer network daemon diff --git a/src/ripple_app/paths/Pathfinder.cpp b/src/ripple_app/paths/Pathfinder.cpp index 7d149a9c1dc..84feeee2eb7 100644 --- a/src/ripple_app/paths/Pathfinder.cpp +++ b/src/ripple_app/paths/Pathfinder.cpp @@ -914,6 +914,7 @@ void Pathfinder::initPathTable() list.push_back(CostedPath_t(6, makePath("safad"))); list.push_back(CostedPath_t(6, makePath("saxfd"))); // source -> gateway -> book to XRP -> book -> destination list.push_back(CostedPath_t(6, makePath("saxfad"))); + list.push_back(CostedPath_t(6, makePath("sabfd"))); // source -> gateway -> book -> book -> destination list.push_back(CostedPath_t(7, makePath("saaad"))); } @@ -927,6 +928,7 @@ void Pathfinder::initPathTable() list.push_back(CostedPath_t(5, makePath("saxfd"))); list.push_back(CostedPath_t(5, makePath("sxfad"))); list.push_back(CostedPath_t(6, makePath("saxfad"))); + list.push_back(CostedPath_t(6, makePath("sabfd"))); list.push_back(CostedPath_t(7, makePath("saafd"))); list.push_back(CostedPath_t(8, makePath("saafad"))); list.push_back(CostedPath_t(9, makePath("safaad"))); diff --git a/src/ripple_app/paths/RippleCalc.cpp b/src/ripple_app/paths/RippleCalc.cpp index 24c17e9e71d..f5264d3bcd5 100644 --- a/src/ripple_app/paths/RippleCalc.cpp +++ b/src/ripple_app/paths/RippleCalc.cpp @@ -2617,7 +2617,7 @@ TER RippleCalc::rippleCalc ( while (temUNCERTAIN == terResult) { int iBest = -1; - const LedgerEntrySet lesCheckpoint = activeLedger; + LedgerEntrySet lesCheckpoint = activeLedger; int iDry = 0; // True, if ever computed multi-quality. @@ -2819,6 +2819,10 @@ TER RippleCalc::rippleCalc ( } else { + // We must restore the activeLedger from lesCheckpoint in the case + // when iBest is -1 and just before the result is set to tesSUCCESS. + + activeLedger.swapWith (lesCheckpoint); terResult = tesSUCCESS; } } diff --git a/src/ripple_app/transactors/Payment.cpp b/src/ripple_app/transactors/Payment.cpp index 311e0770495..f4922746a2e 100644 --- a/src/ripple_app/transactors/Payment.cpp +++ b/src/ripple_app/transactors/Payment.cpp @@ -212,9 +212,14 @@ TER PaymentTransactor::doApply () try { bool const openLedger = is_bit_set (mParams, tapOPEN_LEDGER); - bool const tooManyPaths = spsPaths.size () > MaxPathSize; - terResult = openLedger && tooManyPaths + bool pathTooBig = spsPaths.size () > MaxPathSize; + + for (auto const& path : spsPaths) + if (path.size () > MaxPathLength) + pathTooBig = true; + + terResult = openLedger && pathTooBig ? telBAD_PATH_COUNT // Too many paths for proposed ledger. : RippleCalc::rippleCalc ( mEngine->view (), diff --git a/src/ripple_app/transactors/Payment.h b/src/ripple_app/transactors/Payment.h index 57502336efe..2e935d4a3cb 100644 --- a/src/ripple_app/transactors/Payment.h +++ b/src/ripple_app/transactors/Payment.h @@ -37,6 +37,9 @@ class PaymentTransactor /* The largest number of paths we allow */ static std::size_t const MaxPathSize = 6; + /* The longest path we allow */ + static std::size_t const MaxPathLength = 8; + public: PaymentTransactor ( SerializedTransaction const& txn, diff --git a/src/ripple_app/tx/TransactionMeta.cpp b/src/ripple_app/tx/TransactionMeta.cpp index ceab833383b..f5cf4e60bab 100644 --- a/src/ripple_app/tx/TransactionMeta.cpp +++ b/src/ripple_app/tx/TransactionMeta.cpp @@ -29,7 +29,7 @@ TransactionMetaSet::TransactionMetaSet (uint256 const& txid, std::uint32_t ledge Serializer s (vec); SerializerIterator sit (s); - std::unique_ptr pobj = STObject::deserialize (sit, sfAffectedNodes); + std::unique_ptr pobj = STObject::deserialize (sit, sfMetadata); STObject* obj = static_cast (pobj.get ()); if (!obj) diff --git a/src/ripple_data/protocol/BuildInfo.cpp b/src/ripple_data/protocol/BuildInfo.cpp index e9841bee3fa..53fecbd8bcd 100644 --- a/src/ripple_data/protocol/BuildInfo.cpp +++ b/src/ripple_data/protocol/BuildInfo.cpp @@ -31,7 +31,7 @@ char const* BuildInfo::getRawVersionString () // // The build version number (edit this for each release) // - "0.25.2-rc1" + "0.25.2" // // Must follow the format described here: // diff --git a/src/ripple_data/protocol/FieldNames.cpp b/src/ripple_data/protocol/FieldNames.cpp index 864aab9a148..88d083b7d07 100644 --- a/src/ripple_data/protocol/FieldNames.cpp +++ b/src/ripple_data/protocol/FieldNames.cpp @@ -32,9 +32,10 @@ SField::StaticLockType& SField::getMutex () } SField sfInvalid (-1), sfGeneric (0); -SField sfLedgerEntry (STI_LEDGERENTRY, 1, "LedgerEntry"); -SField sfTransaction (STI_TRANSACTION, 1, "Transaction"); -SField sfValidation (STI_VALIDATION, 1, "Validation"); +SField sfLedgerEntry (STI_LEDGERENTRY, 257, "LedgerEntry"); +SField sfTransaction (STI_TRANSACTION, 257, "Transaction"); +SField sfValidation (STI_VALIDATION, 257, "Validation"); +SField sfMetadata (STI_METADATA, 257, "Metadata"); SField sfHash (STI_HASH256, 257, "hash"); SField sfIndex (STI_HASH256, 258, "index"); diff --git a/src/ripple_data/protocol/FieldNames.h b/src/ripple_data/protocol/FieldNames.h index 858cb01e10b..550c21afc14 100644 --- a/src/ripple_data/protocol/FieldNames.h +++ b/src/ripple_data/protocol/FieldNames.h @@ -39,9 +39,11 @@ enum SerializedTypeID #undef FIELD // high level types + // cannot be serialized inside other types STI_TRANSACTION = 10001, STI_LEDGERENTRY = 10002, STI_VALIDATION = 10003, + STI_METADATA = 10004, }; /** Identifies fields. @@ -239,7 +241,9 @@ class SField SField (SerializedTypeID id, int val); }; -extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation; +extern SField + sfInvalid, sfGeneric, + sfLedgerEntry, sfTransaction, sfValidation, sfMetadata; #define FIELD(name, type, index) extern SField sf##name; #define TYPE(name, type, index) diff --git a/src/ripple_data/protocol/STAmount.cpp b/src/ripple_data/protocol/STAmount.cpp index c6dc5848668..41610b126db 100644 --- a/src/ripple_data/protocol/STAmount.cpp +++ b/src/ripple_data/protocol/STAmount.cpp @@ -223,6 +223,14 @@ std::string STAmount::createHumanCurrency (const uint160& uCurrency) { static uint160 const sIsoBits ("FFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFF"); + // Characters we are willing to include the ASCII representation + // of a three-letter currency code + static std::string legalASCIICurrencyCharacters = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "<>(){}[]|?!@#$%^&*"; + if (uCurrency.isZero ()) { return SYSTEM_CURRENCY_CODE; @@ -244,7 +252,8 @@ std::string STAmount::createHumanCurrency (const uint160& uCurrency) // Specifying the system currency code using ISO-style representation // is not allowed. - if (iso != SYSTEM_CURRENCY_CODE) + if ((iso != SYSTEM_CURRENCY_CODE) && + (iso.find_first_not_of (legalASCIICurrencyCharacters) == std::string::npos)) return iso; } diff --git a/src/ripple_data/protocol/STParsedJSON.cpp b/src/ripple_data/protocol/STParsedJSON.cpp index b014354b6f1..78fde9b605e 100644 --- a/src/ripple_data/protocol/STParsedJSON.cpp +++ b/src/ripple_data/protocol/STParsedJSON.cpp @@ -705,7 +705,7 @@ bool STParsedJSON::parse (std::string const& json_name, "[" << i << "]." << objectName; bool const success (parse (ss.str (), objectFields, nameField, depth + 1, sub_object_)); - if (! success) + if (! success || (sub_object_->getFName().fieldType != STI_OBJECT)) return false; } tail->push_back (*sub_object_); diff --git a/src/ripple_data/protocol/SerializedObject.cpp b/src/ripple_data/protocol/SerializedObject.cpp index 7ae1fdd5c45..ab3ac609feb 100644 --- a/src/ripple_data/protocol/SerializedObject.cpp +++ b/src/ripple_data/protocol/SerializedObject.cpp @@ -277,6 +277,12 @@ bool STObject::set (SerializerIterator& sit, int depth) reachedEndOfObject = (type == STI_OBJECT) && (field == 1); + if ((type == STI_ARRAY) && (field == 1)) + { + WriteLog (lsWARNING, STObject) << "Encountered object with end of array marker"; + throw std::runtime_error ("Illegal terminator in object"); + } + if (!reachedEndOfObject) { // Figure out the field @@ -361,6 +367,12 @@ void STObject::add (Serializer& s, bool withSigningFields) const // insert them in sorted order const SerializedType* field = it.second; + // When we serialize an object inside another object, + // the type associated by rule with this field name + // must be OBJECT, or the object cannot be deserialized + assert ((field->getSType() != STI_OBJECT) || + (field->getFName().fieldType == STI_OBJECT)); + field->addFieldID (s); field->add (s); @@ -1233,6 +1245,12 @@ STArray* STArray::construct (SerializerIterator& sit, SField::ref field) if ((type == STI_ARRAY) && (field == 1)) break; + if ((type == STI_OBJECT) && (field == 1)) + { + WriteLog (lsWARNING, STObject) << "Encountered array with end of object marker"; + throw std::runtime_error ("Illegal terminator in array"); + } + SField::ref fn = SField::getField (type, field); if (fn.isInvalid ()) @@ -1241,6 +1259,12 @@ STArray* STArray::construct (SerializerIterator& sit, SField::ref field) throw std::runtime_error ("Unknown field"); } + if (fn.fieldType != STI_OBJECT) + { + WriteLog (lsTRACE, STObject) << "Array contains non-object"; + throw std::runtime_error ("Non-object in array"); + } + value.push_back (new STObject (fn)); value.rbegin ()->set (sit, 1); } diff --git a/src/ripple_data/protocol/SerializedTypes.cpp b/src/ripple_data/protocol/SerializedTypes.cpp index e44f227f051..eda4dacb95f 100644 --- a/src/ripple_data/protocol/SerializedTypes.cpp +++ b/src/ripple_data/protocol/SerializedTypes.cpp @@ -353,6 +353,8 @@ STVector256* STVector256::construct (SerializerIterator& u, SField::ref name) void STVector256::add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_VECTOR256); s.addVL (mValue.empty () ? nullptr : mValue[0].begin (), mValue.size () * (256 / 8)); } @@ -592,6 +594,8 @@ std::string STPathSet::getText () const void STPathSet::add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_PATHSET); bool bFirst = true; BOOST_FOREACH (const STPath & spPath, value) diff --git a/src/ripple_data/protocol/SerializedTypes.h b/src/ripple_data/protocol/SerializedTypes.h index 6ebf7349f1d..57e8a522f12 100644 --- a/src/ripple_data/protocol/SerializedTypes.h +++ b/src/ripple_data/protocol/SerializedTypes.h @@ -146,13 +146,14 @@ class SerializedType virtual void add (Serializer& s) const { - ; + assert (false); } virtual bool isEquivalent (const SerializedType& t) const; void addFieldID (Serializer& s) const { + assert (fName->isBinary ()); s.addFieldID (fName->fieldType, fName->fieldValue); } @@ -247,6 +248,8 @@ class STUInt8 : public SerializedType Json::Value getJson (int) const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_UINT8); s.add8 (value); } @@ -306,6 +309,8 @@ class STUInt16 : public SerializedType Json::Value getJson (int) const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_UINT16); s.add16 (value); } @@ -365,6 +370,8 @@ class STUInt32 : public SerializedType Json::Value getJson (int) const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_UINT32); s.add32 (value); } @@ -423,6 +430,8 @@ class STUInt64 : public SerializedType Json::Value getJson (int) const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_UINT64); s.add64 (value); } @@ -881,6 +890,8 @@ class STHash128 : public SerializedType virtual std::string getText () const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_HASH128); s.add128 (value); } @@ -954,6 +965,8 @@ class STHash160 : public SerializedType virtual std::string getText () const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_HASH160); s.add160 (value); } @@ -1027,6 +1040,8 @@ class STHash256 : public SerializedType std::string getText () const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert (fName->fieldType == STI_HASH256); s.add256 (value); } @@ -1094,6 +1109,9 @@ class STVariableLength : public SerializedType virtual std::string getText () const; void add (Serializer& s) const { + assert (fName->isBinary ()); + assert ((fName->fieldType == STI_VL) || + (fName->fieldType == STI_ACCOUNT)); s.addVL (value); }