From 148bbf4e8faf426ee047a2f6657d64b77f184b5b Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Fri, 21 Dec 2018 17:13:58 -0500 Subject: [PATCH] Add safe_cast (RIPD-1702): This change ensures that no overflow can occur when casting between enums and integral types. --- CMakeLists.txt | 1 + src/ripple/app/main/Application.cpp | 3 +- src/ripple/app/misc/NetworkOPs.cpp | 7 +- src/ripple/app/misc/impl/LoadFeeTrack.cpp | 5 +- src/ripple/app/tx/impl/Escrow.cpp | 3 +- src/ripple/basics/impl/Sustain.cpp | 5 +- src/ripple/basics/safe_cast.h | 78 +++++++++++++++++++++ src/ripple/conditions/impl/Fulfillment.cpp | 14 ++-- src/ripple/conditions/impl/error.cpp | 5 +- src/ripple/ledger/ApplyView.h | 24 ++++--- src/ripple/ledger/CashDiff.h | 5 +- src/ripple/nodestore/NodeObject.h | 1 + src/ripple/nodestore/impl/DecodedBlob.cpp | 3 +- src/ripple/overlay/impl/Message.cpp | 3 +- src/ripple/overlay/impl/PeerImp.cpp | 3 +- src/ripple/overlay/impl/TMHello.cpp | 11 +-- src/ripple/overlay/impl/TrafficCount.h | 3 +- src/ripple/protocol/SField.h | 3 +- src/ripple/protocol/Serializer.h | 7 +- src/ripple/protocol/TER.h | 13 ++-- src/ripple/protocol/impl/SField.cpp | 5 +- src/ripple/protocol/impl/STAmount.cpp | 5 +- src/ripple/protocol/impl/STInteger.cpp | 9 +-- src/ripple/protocol/impl/STLedgerEntry.cpp | 7 +- src/ripple/protocol/impl/STParsedJSON.cpp | 15 +++- src/ripple/protocol/impl/STTx.cpp | 17 ++--- src/ripple/protocol/impl/tokens.cpp | 7 +- src/ripple/rpc/impl/ServerHandlerImp.cpp | 7 +- src/ripple/rpc/impl/ShardArchiveHandler.cpp | 4 +- src/ripple/server/impl/BaseWSPeer.h | 6 +- src/ripple/server/impl/Port.cpp | 3 +- src/test/app/PayStrand_test.cpp | 6 +- src/test/jtx/impl/amount.cpp | 3 +- src/test/nodestore/Timing_test.cpp | 3 +- src/test/peerfinder/Livecache_test.cpp | 5 +- 35 files changed, 213 insertions(+), 86 deletions(-) create mode 100644 src/ripple/basics/safe_cast.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 835a073ee..d5aa0979d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1474,6 +1474,7 @@ install ( src/ripple/basics/FileUtilities.h src/ripple/basics/LocalValue.h src/ripple/basics/Log.h + src/ripple/basics/safe_cast.h src/ripple/basics/Slice.h src/ripple/basics/StringUtilities.h src/ripple/basics/ToString.h diff --git a/src/ripple/app/main/Application.cpp b/src/ripple/app/main/Application.cpp index ba3f0b5b4..8a33e49c6 100644 --- a/src/ripple/app/main/Application.cpp +++ b/src/ripple/app/main/Application.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1068,7 +1069,7 @@ public: *db << "PRAGMA page_count;", soci::into(pageCount); std::uint32_t freePages = maxPages - pageCount; std::uint64_t freeSpace = - static_cast(freePages) * pageSize; + safe_cast(freePages) * pageSize; JLOG(m_journal.info()) << "Transaction DB pathname: " << dbPath.string() << "; file size: " << dbSize.value_or(-1) << " bytes" diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index d31a70aa0..4383acdcb 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -1664,7 +1665,7 @@ void NetworkOPsImp::pubServer () if(f.em) { auto const loadFactor = - std::max(static_cast(f.loadFactorServer), + std::max(safe_cast(f.loadFactorServer), mulDiv(f.em->openLedgerFeeLevel, f.loadBaseServer, f.em->referenceFeeLevel).second); @@ -2121,7 +2122,7 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters) { if (when) info[jss::validator_list_expires] = - static_cast(when->time_since_epoch().count()); + safe_cast(when->time_since_epoch().count()); else info[jss::validator_list_expires] = 0; } @@ -2227,7 +2228,7 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin, bool counters) auto const loadBaseFeeEscalation = escalationMetrics.referenceFeeLevel; - auto const loadFactor = std::max(static_cast(loadFactorServer), + auto const loadFactor = std::max(safe_cast(loadFactorServer), mulDiv(loadFactorFeeEscalation, loadBaseServer, loadBaseFeeEscalation).second); if (!human) diff --git a/src/ripple/app/misc/impl/LoadFeeTrack.cpp b/src/ripple/app/misc/impl/LoadFeeTrack.cpp index 25242909b..1dadc1da1 100644 --- a/src/ripple/app/misc/impl/LoadFeeTrack.cpp +++ b/src/ripple/app/misc/impl/LoadFeeTrack.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -149,8 +150,8 @@ scaleFeeLoad(std::uint64_t fee, LoadFeeTrack const& feeTrack, // The denominator of the fraction we're trying to compute. // fees.units and lftNormalFee are both 32 bit, // so the multiplication can't overflow. - auto den = static_cast(fees.units) - * static_cast(feeTrack.getLoadBase()); + auto den = safe_cast(fees.units) + * safe_cast(feeTrack.getLoadBase()); // Reduce fee * baseFee * feeFactor / (fees.units * lftNormalFee) // to lowest terms. lowestTerms(fee, den); diff --git a/src/ripple/app/tx/impl/Escrow.cpp b/src/ripple/app/tx/impl/Escrow.cpp index 4ad934ab8..b1b36e778 100644 --- a/src/ripple/app/tx/impl/Escrow.cpp +++ b/src/ripple/app/tx/impl/Escrow.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -358,7 +359,7 @@ EscrowFinish::calculateBaseFee ( if (auto const fb = tx[~sfFulfillment]) { extraFee += view.fees().units * - (32 + static_cast (fb->size() / 16)); + (32 + safe_cast (fb->size() / 16)); } return Transactor::calculateBaseFee (view, tx) + extraFee; diff --git a/src/ripple/basics/impl/Sustain.cpp b/src/ripple/basics/impl/Sustain.cpp index 2ca30c6d0..a9d313796 100644 --- a/src/ripple/basics/impl/Sustain.cpp +++ b/src/ripple/basics/impl/Sustain.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -41,8 +42,8 @@ namespace ripple { static auto const sleepBeforeWaiting = 10; static auto const sleepBetweenWaits = 1; -static pid_t pManager = static_cast (0); -static pid_t pChild = static_cast (0); +static pid_t pManager = safe_cast (0); +static pid_t pChild = safe_cast (0); static void pass_signal (int a) { diff --git a/src/ripple/basics/safe_cast.h b/src/ripple/basics/safe_cast.h new file mode 100644 index 000000000..80422c02d --- /dev/null +++ b/src/ripple/basics/safe_cast.h @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2018 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_BASICS_SAFE_CAST_H_INCLUDED +#define RIPPLE_BASICS_SAFE_CAST_H_INCLUDED + +#include + +namespace ripple { + +// safe_cast adds compile-time checks to a static_cast to ensure that +// the destination can hold all values of the source. This is particularly +// handy when the source or destination is an enumeration type. + +template +inline +constexpr +std::enable_if_t +< + std::is_integral::value && std::is_integral::value, + Dest +> +safe_cast(Src s) noexcept +{ + static_assert(std::is_signed::value || std::is_unsigned::value, + "Cannot cast signed to unsigned"); + constexpr unsigned not_same = std::is_signed::value != + std::is_signed::value; + static_assert(sizeof(Dest) >= sizeof(Src) + not_same, + "Destination is too small to hold all values of source"); + return static_cast(s); +} + +template +inline +constexpr +std::enable_if_t +< + std::is_enum::value && std::is_integral::value, + Dest +> +safe_cast(Src s) noexcept +{ + return static_cast(safe_cast>(s)); +} + +template +inline +constexpr +std::enable_if_t +< + std::is_integral::value && std::is_enum::value, + Dest +> +safe_cast(Src s) noexcept +{ + return safe_cast(static_cast>(s)); +} + +} // ripple + +#endif diff --git a/src/ripple/conditions/impl/Fulfillment.cpp b/src/ripple/conditions/impl/Fulfillment.cpp index cbb658573..6fbd28b8d 100644 --- a/src/ripple/conditions/impl/Fulfillment.cpp +++ b/src/ripple/conditions/impl/Fulfillment.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -116,31 +117,32 @@ Fulfillment::deserialize( std::unique_ptr f; - switch (static_cast(p.tag)) + using TagType = decltype(p.tag); + switch (p.tag) { - case Type::preimageSha256: + case safe_cast(Type::preimageSha256): f = PreimageSha256::deserialize(Slice(s.data(), p.length), ec); if (ec) return {}; s += p.length; break; - case Type::prefixSha256: + case safe_cast(Type::prefixSha256): ec = error::unsupported_type; return {}; break; - case Type::thresholdSha256: + case safe_cast(Type::thresholdSha256): ec = error::unsupported_type; return {}; break; - case Type::rsaSha256: + case safe_cast(Type::rsaSha256): ec = error::unsupported_type; return {}; break; - case Type::ed25519Sha256: + case safe_cast(Type::ed25519Sha256): ec = error::unsupported_type; return {}; diff --git a/src/ripple/conditions/impl/error.cpp b/src/ripple/conditions/impl/error.cpp index 647215989..1ecc14df9 100644 --- a/src/ripple/conditions/impl/error.cpp +++ b/src/ripple/conditions/impl/error.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -41,7 +42,7 @@ public: std::string message(int ev) const override { - switch (static_cast(ev)) + switch (safe_cast(ev)) { case error::unsupported_type: return "Specification: Requested type not supported."; @@ -136,7 +137,7 @@ std::error_code make_error_code(error ev) { return std::error_code { - static_cast::type>(ev), + safe_cast::type>(ev), detail::get_cryptoconditions_error_category() }; } diff --git a/src/ripple/ledger/ApplyView.h b/src/ripple/ledger/ApplyView.h index 9328b15ee..b23873338 100644 --- a/src/ripple/ledger/ApplyView.h +++ b/src/ripple/ledger/ApplyView.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED #define RIPPLE_LEDGER_APPLYVIEW_H_INCLUDED +#include #include #include #include @@ -27,6 +28,7 @@ namespace ripple { enum ApplyFlags + : std::uint32_t { tapNONE = 0x00, @@ -48,14 +50,14 @@ ApplyFlags operator|(ApplyFlags const& lhs, ApplyFlags const& rhs) { - return static_cast( - static_cast>(lhs) | - static_cast>(rhs)); + return safe_cast( + safe_cast>(lhs) | + safe_cast>(rhs)); } -static_assert((tapPREFER_QUEUE | tapRETRY) == static_cast(0x60), +static_assert((tapPREFER_QUEUE | tapRETRY) == safe_cast(0x60u), "ApplyFlags operator |"); -static_assert((tapRETRY | tapPREFER_QUEUE) == static_cast(0x60), +static_assert((tapRETRY | tapPREFER_QUEUE) == safe_cast(0x60u), "ApplyFlags operator |"); constexpr @@ -63,9 +65,9 @@ ApplyFlags operator&(ApplyFlags const& lhs, ApplyFlags const& rhs) { - return static_cast( - static_cast>(lhs) & - static_cast>(rhs)); + return safe_cast( + safe_cast>(lhs) & + safe_cast>(rhs)); } static_assert((tapPREFER_QUEUE & tapRETRY) == tapNONE, @@ -77,11 +79,11 @@ constexpr ApplyFlags operator~(ApplyFlags const& flags) { - return static_cast( - ~static_cast>(flags)); + return safe_cast( + ~safe_cast>(flags)); } -static_assert(~tapRETRY == static_cast(~0x20), +static_assert(~tapRETRY == safe_cast(0xFFFFFFDFu), "ApplyFlags operator ~"); inline diff --git a/src/ripple/ledger/CashDiff.h b/src/ripple/ledger/CashDiff.h index 53d130a43..9ed552139 100644 --- a/src/ripple/ledger/CashDiff.h +++ b/src/ripple/ledger/CashDiff.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_LEDGER_CASHDIFF_H_INCLUDED #define RIPPLE_LEDGER_CASHDIFF_H_INCLUDED +#include #include #include // std::unique_ptr @@ -44,13 +45,13 @@ inline CashFilter operator| (CashFilter lhs, CashFilter rhs) { using ul_t = std::underlying_type::type; return static_cast( - static_cast(lhs) | static_cast(rhs)); + safe_cast(lhs) | safe_cast(rhs)); } inline CashFilter operator& (CashFilter lhs, CashFilter rhs) { using ul_t = std::underlying_type::type; return static_cast( - static_cast(lhs) & static_cast(rhs)); + safe_cast(lhs) & safe_cast(rhs)); } //------------------------------------------------------------------------------ diff --git a/src/ripple/nodestore/NodeObject.h b/src/ripple/nodestore/NodeObject.h index ef06d49a1..7da09a5e6 100644 --- a/src/ripple/nodestore/NodeObject.h +++ b/src/ripple/nodestore/NodeObject.h @@ -29,6 +29,7 @@ namespace ripple { /** The types of node objects. */ enum NodeObjectType + : std::uint32_t { hotUNKNOWN = 0, hotLEDGER = 1, diff --git a/src/ripple/nodestore/impl/DecodedBlob.cpp b/src/ripple/nodestore/impl/DecodedBlob.cpp index f1ffbf3f6..0d7495b4b 100644 --- a/src/ripple/nodestore/impl/DecodedBlob.cpp +++ b/src/ripple/nodestore/impl/DecodedBlob.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -48,7 +49,7 @@ DecodedBlob::DecodedBlob (void const* key, void const* value, int valueBytes) if (valueBytes > 8) { unsigned char const* byte = static_cast (value); - m_objectType = static_cast (byte [8]); + m_objectType = safe_cast (byte [8]); } if (valueBytes > 9) diff --git a/src/ripple/overlay/impl/Message.cpp b/src/ripple/overlay/impl/Message.cpp index 6de4de73f..122ab998d 100644 --- a/src/ripple/overlay/impl/Message.cpp +++ b/src/ripple/overlay/impl/Message.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -38,7 +39,7 @@ Message::Message (::google::protobuf::Message const& message, int type) message.SerializeToArray (&mBuffer [Message::kHeaderBytes], messageBytes); } - mCategory = static_cast(TrafficCount::categorize + mCategory = safe_cast(TrafficCount::categorize (message, type, false)); } diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index a3492cdd0..ca836fdbf 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -192,7 +193,7 @@ PeerImp::send (Message::pointer const& m) return; overlay_.reportTraffic ( - static_cast(m->getCategory()), + safe_cast(m->getCategory()), false, static_cast(m->getBuffer().size())); auto sendq_size = send_queue_.size(); diff --git a/src/ripple/overlay/impl/TMHello.cpp b/src/ripple/overlay/impl/TMHello.cpp index a2bbaf1ee..45a3d7c39 100644 --- a/src/ripple/overlay/impl/TMHello.cpp +++ b/src/ripple/overlay/impl/TMHello.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -226,11 +227,11 @@ parseHello (bool request, boost::beast::http::fields const& h, beast::Journal jo if (versions.empty()) return boost::none; hello.set_protoversion( - (static_cast(versions.back().first) << 16) | - (static_cast(versions.back().second))); + (safe_cast(versions.back().first) << 16) | + (safe_cast(versions.back().second))); hello.set_protoversionmin( - (static_cast(versions.front().first) << 16) | - (static_cast(versions.front().second))); + (safe_cast(versions.front().first) << 16) | + (safe_cast(versions.front().second))); } { @@ -362,7 +363,7 @@ verifyHello (protocol::TMHello const& h, JLOG(journal.trace()) << "Connect: time offset " << - static_cast(ourTime) - h.nettime(); + safe_cast(ourTime) - h.nettime(); } if (h.protoversionmin () > to_packed (BuildInfo::getCurrentProtocol())) diff --git a/src/ripple/overlay/impl/TrafficCount.h b/src/ripple/overlay/impl/TrafficCount.h index 39df856da..ea5d99980 100644 --- a/src/ripple/overlay/impl/TrafficCount.h +++ b/src/ripple/overlay/impl/TrafficCount.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_OVERLAY_TRAFFIC_H_INCLUDED #define RIPPLE_OVERLAY_TRAFFIC_H_INCLUDED +#include #include #include @@ -99,7 +100,7 @@ public: { for (category i = category::CT_base; i <= category::CT_unknown; - i = static_cast(static_cast(i) + 1)) + i = safe_cast(safe_cast>(i) + 1)) { counts_[i]; } diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index 85e6e4940..d0b50ccb9 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_PROTOCOL_SFIELD_H_INCLUDED #define RIPPLE_PROTOCOL_SFIELD_H_INCLUDED +#include #include #include #include @@ -86,7 +87,7 @@ inline int field_code(SerializedTypeID id, int index) { - return (static_cast(id) << 16) | index; + return (safe_cast(id) << 16) | index; } // constexpr diff --git a/src/ripple/protocol/Serializer.h b/src/ripple/protocol/Serializer.h index 6192be29e..f2c2890ae 100644 --- a/src/ripple/protocol/Serializer.h +++ b/src/ripple/protocol/Serializer.h @@ -20,12 +20,13 @@ #ifndef RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED #define RIPPLE_PROTOCOL_SERIALIZER_H_INCLUDED -#include #include #include #include +#include #include #include +#include #include #include #include @@ -158,7 +159,7 @@ public: int addFieldID (int type, int name); int addFieldID (SerializedTypeID type, int name) { - return addFieldID (static_cast (type), name); + return addFieldID (safe_cast (type), name); } // DEPRECATED @@ -266,7 +267,7 @@ public: std::setw (2) << std::hex << std::setfill ('0') << - static_cast(element); + safe_cast(element); } return h.str (); } diff --git a/src/ripple/protocol/TER.h b/src/ripple/protocol/TER.h index b7473f145..04775f472 100644 --- a/src/ripple/protocol/TER.h +++ b/src/ripple/protocol/TER.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_PROTOCOL_TER_H_INCLUDED #define RIPPLE_PROTOCOL_TER_H_INCLUDED +#include #include #include @@ -270,22 +271,22 @@ enum TECcodes : TERUnderlyingType // For generic purposes, a free function that returns the value of a TE*codes. constexpr TERUnderlyingType TERtoInt (TELcodes v) -{ return static_cast(v); } +{ return safe_cast(v); } constexpr TERUnderlyingType TERtoInt (TEMcodes v) -{ return static_cast(v); } +{ return safe_cast(v); } constexpr TERUnderlyingType TERtoInt (TEFcodes v) -{ return static_cast(v); } +{ return safe_cast(v); } constexpr TERUnderlyingType TERtoInt (TERcodes v) -{ return static_cast(v); } +{ return safe_cast(v); } constexpr TERUnderlyingType TERtoInt (TEScodes v) -{ return static_cast(v); } +{ return safe_cast(v); } constexpr TERUnderlyingType TERtoInt (TECcodes v) -{ return static_cast(v); } +{ return safe_cast(v); } //------------------------------------------------------------------------------ // Template class that is specific to selected ranges of error codes. The diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index 5aeaddd28..e285f9e16 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -358,7 +359,7 @@ SField::getField (int code) if (it != unknownCodeToField.end ()) return * (it->second); return *(unknownCodeToField[code] = std::unique_ptr( - new SField(static_cast(type), field))); + new SField(safe_cast(type), field))); } } @@ -385,7 +386,7 @@ std::string SField::getName () const if (fieldValue == 0) return ""; - return std::to_string(static_cast (fieldType)) + "/" + + return std::to_string(safe_cast (fieldType)) + "/" + std::to_string(fieldValue); } diff --git a/src/ripple/protocol/impl/STAmount.cpp b/src/ripple/protocol/impl/STAmount.cpp index 616927f6a..68306ba63 100644 --- a/src/ripple/protocol/impl/STAmount.cpp +++ b/src/ripple/protocol/impl/STAmount.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -246,13 +247,13 @@ STAmount::STAmount (Issue const& issue, STAmount::STAmount (Issue const& issue, std::uint32_t mantissa, int exponent, bool negative) - : STAmount (issue, static_cast(mantissa), exponent, negative) + : STAmount (issue, safe_cast(mantissa), exponent, negative) { } STAmount::STAmount (Issue const& issue, int mantissa, int exponent) - : STAmount (issue, static_cast(mantissa), exponent) + : STAmount (issue, safe_cast(mantissa), exponent) { } diff --git a/src/ripple/protocol/impl/STInteger.cpp b/src/ripple/protocol/impl/STInteger.cpp index ab44f24ac..a31899e08 100644 --- a/src/ripple/protocol/impl/STInteger.cpp +++ b/src/ripple/protocol/impl/STInteger.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -98,7 +99,7 @@ STUInt16::getText () const if (getFName () == sfLedgerEntryType) { auto item = LedgerFormats::getInstance ().findByType ( - static_cast (value_)); + safe_cast (value_)); if (item != nullptr) return item->getName (); @@ -107,7 +108,7 @@ STUInt16::getText () const if (getFName () == sfTransactionType) { auto item =TxFormats::getInstance().findByType ( - static_cast (value_)); + safe_cast (value_)); if (item != nullptr) return item->getName (); @@ -123,7 +124,7 @@ STUInt16::getJson (int) const if (getFName () == sfLedgerEntryType) { auto item = LedgerFormats::getInstance ().findByType ( - static_cast (value_)); + safe_cast (value_)); if (item != nullptr) return item->getName (); @@ -132,7 +133,7 @@ STUInt16::getJson (int) const if (getFName () == sfTransactionType) { auto item = TxFormats::getInstance().findByType ( - static_cast (value_)); + safe_cast (value_)); if (item != nullptr) return item->getName (); diff --git a/src/ripple/protocol/impl/STLedgerEntry.cpp b/src/ripple/protocol/impl/STLedgerEntry.cpp index f22c41982..15f011091 100644 --- a/src/ripple/protocol/impl/STLedgerEntry.cpp +++ b/src/ripple/protocol/impl/STLedgerEntry.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,10 @@ STLedgerEntry::STLedgerEntry (Keylet const& k) , key_ (k.key) , type_ (k.type) { + if (!(0u <= type_ && + type_ <= std::min(std::numeric_limits::max(), + std::numeric_limits>::max()))) + Throw ("invalid ledger entry type: out of range"); auto const format = LedgerFormats::getInstance().findByType (type_); @@ -66,7 +71,7 @@ STLedgerEntry::STLedgerEntry ( void STLedgerEntry::setSLEType () { auto format = LedgerFormats::getInstance().findByType ( - static_cast ( + safe_cast ( getFieldU16 (sfLedgerEntryType))); if (format == nullptr) diff --git a/src/ripple/protocol/impl/STParsedJSON.cpp b/src/ripple/protocol/impl/STParsedJSON.cpp index 986d90ad3..a92b83e79 100644 --- a/src/ripple/protocol/impl/STParsedJSON.cpp +++ b/src/ripple/protocol/impl/STParsedJSON.cpp @@ -18,6 +18,7 @@ //============================================================================== #include +#include #include #include #include @@ -275,6 +276,9 @@ static boost::optional parseLeaf ( TxType const txType (TxFormats::getInstance(). findTypeByName (strValue)); + if (txType == ttINVALID) + Throw( + "Invalid transaction format name"); ret = detail::make_stvar (field, static_cast (txType)); @@ -287,6 +291,13 @@ static boost::optional parseLeaf ( LedgerFormats::getInstance(). findTypeByName (strValue)); + if (!(0u <= type && + type <= std::min( + std::numeric_limits::max(), + std::numeric_limits>::max()))) + Throw( + "Invalid ledger entry type: out of range"); ret = detail::make_stvar (field, static_cast (type)); @@ -346,7 +357,7 @@ static boost::optional parseLeaf ( else if (value.isUInt ()) { ret = detail::make_stvar (field, - static_cast (value.asUInt ())); + safe_cast (value.asUInt ())); } else { @@ -378,7 +389,7 @@ static boost::optional parseLeaf ( else if (value.isUInt ()) { ret = detail::make_stvar (field, - static_cast (value.asUInt ())); + safe_cast (value.asUInt ())); } else { diff --git a/src/ripple/protocol/impl/STTx.cpp b/src/ripple/protocol/impl/STTx.cpp index 3b7361ee3..0fe820412 100644 --- a/src/ripple/protocol/impl/STTx.cpp +++ b/src/ripple/protocol/impl/STTx.cpp @@ -17,6 +17,10 @@ */ //============================================================================== +#include +#include +#include +#include #include #include #include @@ -27,9 +31,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -49,7 +50,7 @@ auto getTxFormat (TxType type) Throw ( "Invalid transaction type " + std::to_string ( - static_cast>(type))); + safe_cast>(type))); } return format; @@ -58,7 +59,7 @@ auto getTxFormat (TxType type) STTx::STTx (STObject&& object) noexcept (false) : STObject (std::move (object)) { - tx_type_ = static_cast (getFieldU16 (sfTransactionType)); + tx_type_ = safe_cast (getFieldU16 (sfTransactionType)); applyTemplate (getTxFormat (tx_type_)->elements); // may throw tid_ = getHash(HashPrefix::transactionID); } @@ -74,7 +75,7 @@ STTx::STTx (SerialIter& sit) noexcept (false) if (set (sit)) Throw ("Transaction contains an object terminator"); - tx_type_ = static_cast (getFieldU16 (sfTransactionType)); + tx_type_ = safe_cast (getFieldU16 (sfTransactionType)); applyTemplate (getTxFormat (tx_type_)->elements); // May throw tid_ = getHash(HashPrefix::transactionID); @@ -92,7 +93,7 @@ STTx::STTx ( assembler (*this); - tx_type_ = static_cast(getFieldU16 (sfTransactionType)); + tx_type_ = safe_cast(getFieldU16 (sfTransactionType)); if (tx_type_ != type) LogicError ("Transaction type was mutated during assembly"); @@ -523,7 +524,7 @@ isPseudoTx(STObject const& tx) auto t = tx[~sfTransactionType]; if (!t) return false; - auto tt = static_cast(*t); + auto tt = safe_cast(*t); return tt == ttAMENDMENT || tt == ttFEE; } diff --git a/src/ripple/protocol/impl/tokens.cpp b/src/ripple/protocol/impl/tokens.cpp index 2e7e5d340..9fb6d7935 100644 --- a/src/ripple/protocol/impl/tokens.cpp +++ b/src/ripple/protocol/impl/tokens.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -166,7 +167,7 @@ encodeToken (TokenType type, // Lay the data out as // - buf[0] = static_cast>(type); + buf[0] = safe_cast>(type); if (size) std::memcpy(buf.data() + 1, token, size); checksum(buf.data() + 1 + size, buf.data(), 1 + size); @@ -259,14 +260,14 @@ std::string decodeBase58Token (std::string const& s, TokenType type, InverseArray const& inv) { - auto ret = decodeBase58(s, inv); + std::string const ret = decodeBase58(s, inv); // Reject zero length tokens if (ret.size() < 6) return {}; // The type must match. - if (type != static_cast(ret[0])) + if (type != safe_cast(static_cast(ret[0]))) return {}; // And the checksum must as well. diff --git a/src/ripple/rpc/impl/ServerHandlerImp.cpp b/src/ripple/rpc/impl/ServerHandlerImp.cpp index ed5050015..12f010136 100644 --- a/src/ripple/rpc/impl/ServerHandlerImp.cpp +++ b/src/ripple/rpc/impl/ServerHandlerImp.cpp @@ -864,12 +864,11 @@ ServerHandlerImp::processRequest (Port const& port, } auto response = to_string (reply); - rpc_time_.notify (static_cast ( + rpc_time_.notify ( std::chrono::duration_cast ( - std::chrono::high_resolution_clock::now () - start))); + std::chrono::high_resolution_clock::now () - start)); ++rpc_requests_; - rpc_size_.notify (static_cast ( - response.size ())); + rpc_size_.notify (beast::insight::Event::value_type{response.size()}); response += '\n'; diff --git a/src/ripple/rpc/impl/ShardArchiveHandler.cpp b/src/ripple/rpc/impl/ShardArchiveHandler.cpp index 6bcf37ea2..b45a7064a 100644 --- a/src/ripple/rpc/impl/ShardArchiveHandler.cpp +++ b/src/ripple/rpc/impl/ShardArchiveHandler.cpp @@ -187,8 +187,8 @@ ShardArchiveHandler::complete(path dstPath) auto const mode {ptr->app_.getOPs().getOperatingMode()}; if (ptr->validate_ && mode != NetworkOPs::omFULL) { - timer_.expires_from_now(static_cast( - (NetworkOPs::omFULL - mode) * 10)); + timer_.expires_from_now(std::chrono::seconds{ + (NetworkOPs::omFULL - mode) * 10}); timer_.async_wait( [=, dstPath = std::move(dstPath), ptr = std::move(ptr)] (boost::system::error_code const& ec) diff --git a/src/ripple/server/impl/BaseWSPeer.h b/src/ripple/server/impl/BaseWSPeer.h index 2573e6c7d..c4fc9b79d 100644 --- a/src/ripple/server/impl/BaseWSPeer.h +++ b/src/ripple/server/impl/BaseWSPeer.h @@ -20,6 +20,7 @@ #ifndef RIPPLE_SERVER_BASEWSPEER_H_INCLUDED #define RIPPLE_SERVER_BASEWSPEER_H_INCLUDED +#include #include #include #include @@ -214,8 +215,9 @@ send(std::shared_ptr w) { JLOG(this->j_.info()) << "closing slow client"; - cr_.code = static_cast(4000); - cr_.reason = "Client is too slow."; + cr_.code = safe_cast + (boost::beast::websocket::close_code::policy_error); + cr_.reason = "Policy error: client is too slow."; wq_.erase(std::next(wq_.begin()), wq_.end()); close(); return; diff --git a/src/ripple/server/impl/Port.cpp b/src/ripple/server/impl/Port.cpp index 7848ded24..dee424079 100644 --- a/src/ripple/server/impl/Port.cpp +++ b/src/ripple/server/impl/Port.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -192,7 +193,7 @@ parse_Port (ParsedPort& port, Section const& section, std::ostream& log) { try { - port.limit = static_cast ( + port.limit = safe_cast ( beast::lexicalCastThrow(lim)); } catch (std::exception const&) diff --git a/src/test/app/PayStrand_test.cpp b/src/test/app/PayStrand_test.cpp index 8495f4543..d0df61ac0 100644 --- a/src/test/app/PayStrand_test.cpp +++ b/src/test/app/PayStrand_test.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -183,6 +184,7 @@ allpe(AccountID const& a, Issue const& iss) class ElementComboIter { enum class SB /*state bit*/ + : std::uint16_t { acc, iss, cur, @@ -200,7 +202,7 @@ class ElementComboIter last }; std::uint16_t state_ = 0; - static_assert(static_cast(SB::last) <= sizeof(decltype(state_)) * 8, ""); + static_assert(safe_cast(SB::last) <= sizeof(decltype(state_)) * 8, ""); STPathElement const* prev_ = nullptr; // disallow iss and cur to be specified with acc is specified (simplifies some tests) bool const allowCompound_ = false; @@ -208,7 +210,7 @@ class ElementComboIter bool has(SB s) const { - return state_ & (1 << static_cast(s)); + return state_ & (1 << safe_cast(s)); } bool diff --git a/src/test/jtx/impl/amount.cpp b/src/test/jtx/impl/amount.cpp index 9e9cb155a..e1c4ecbcf 100644 --- a/src/test/jtx/impl/amount.cpp +++ b/src/test/jtx/impl/amount.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -119,7 +120,7 @@ PrettyAmount IOU::operator()(detail::epsilon_multiple m) const { return { STAmount(issue(), - static_cast(m.n), -81), + safe_cast(m.n), -81), account.name() }; } diff --git a/src/test/nodestore/Timing_test.cpp b/src/test/nodestore/Timing_test.cpp index 14a4e100b..5dca0dbff 100644 --- a/src/test/nodestore/Timing_test.cpp +++ b/src/test/nodestore/Timing_test.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -121,7 +122,7 @@ public: Blob value(d_size_(gen_)); rngcpy (&value[0], value.size(), gen_); return NodeObject::createObject ( - static_cast(d_type_(gen_)), + safe_cast(d_type_(gen_)), std::move(value), key); } diff --git a/src/test/peerfinder/Livecache_test.cpp b/src/test/peerfinder/Livecache_test.cpp index 89f9d594b..b365275a0 100644 --- a/src/test/peerfinder/Livecache_test.cpp +++ b/src/test/peerfinder/Livecache_test.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -134,7 +135,7 @@ public: add( beast::IP::randomEP(true), c, - ripple::rand_int(0, static_cast(Tuning::maxHops + 1))); + ripple::rand_int(0, safe_cast(Tuning::maxHops + 1))); auto h = c.hops.histogram(); if(! BEAST_EXPECT(! h.empty())) return; @@ -159,7 +160,7 @@ public: add( beast::IP::randomEP(true), c, - ripple::rand_int(0, static_cast(Tuning::maxHops + 1))); + ripple::rand_int(0, safe_cast(Tuning::maxHops + 1))); using at_hop = std::vector ; using all_hops = std::array ;