diff --git a/src/ripple/app/reporting/ETLSource.cpp b/src/ripple/app/reporting/ETLSource.cpp index 5036ca9102..09eef5a609 100644 --- a/src/ripple/app/reporting/ETLSource.cpp +++ b/src/ripple/app/reporting/ETLSource.cpp @@ -495,11 +495,14 @@ public: for (auto& obj : cur_->ledger_objects().objects()) { - auto key = uint256::fromVoid(obj.key().data()); + auto key = uint256::fromVoidChecked(obj.key()); + if (!key) + throw std::runtime_error("Received malformed object ID"); + auto& data = obj.data(); SerialIter it{data.data(), data.size()}; - std::shared_ptr sle = std::make_shared(it, key); + std::shared_ptr sle = std::make_shared(it, *key); queue.push(sle); } diff --git a/src/ripple/app/reporting/ReportingETL.cpp b/src/ripple/app/reporting/ReportingETL.cpp index e36cdbee03..4db578b546 100644 --- a/src/ripple/app/reporting/ReportingETL.cpp +++ b/src/ripple/app/reporting/ReportingETL.cpp @@ -405,32 +405,35 @@ ReportingETL::buildNextLedger( for (auto& obj : rawData.ledger_objects().objects()) { - auto key = uint256::fromVoid(obj.key().data()); + auto key = uint256::fromVoidChecked(obj.key()); + if (!key) + throw std::runtime_error("Recevied malformed object ID"); + auto& data = obj.data(); // indicates object was deleted if (data.size() == 0) { JLOG(journal_.trace()) << __func__ << " : " - << "Erasing object = " << key; - if (next->exists(key)) - next->rawErase(key); + << "Erasing object = " << *key; + if (next->exists(*key)) + next->rawErase(*key); } else { SerialIter it{data.data(), data.size()}; - std::shared_ptr sle = std::make_shared(it, key); + std::shared_ptr sle = std::make_shared(it, *key); - if (next->exists(key)) + if (next->exists(*key)) { JLOG(journal_.trace()) << __func__ << " : " - << "Replacing object = " << key; + << "Replacing object = " << *key; next->rawReplace(sle); } else { JLOG(journal_.trace()) << __func__ << " : " - << "Inserting object = " << key; + << "Inserting object = " << *key; next->rawInsert(sle); } } diff --git a/src/ripple/basics/base_uint.h b/src/ripple/basics/base_uint.h index a6a33a5097..23ac188ab4 100644 --- a/src/ripple/basics/base_uint.h +++ b/src/ripple/basics/base_uint.h @@ -313,6 +313,15 @@ public: return base_uint(data, VoidHelper()); } + template + static std::optional + fromVoidChecked(T const& from) + { + if (from.size() != size()) + return {}; + return fromVoid(from.data()); + } + constexpr int signum() const { diff --git a/src/ripple/rpc/handlers/AccountTx.cpp b/src/ripple/rpc/handlers/AccountTx.cpp index 7dae496e95..e383b66fee 100644 --- a/src/ripple/rpc/handlers/AccountTx.cpp +++ b/src/ripple/rpc/handlers/AccountTx.cpp @@ -97,14 +97,17 @@ parseLedgerArgs( } else if (ledgerCase == LedgerCase::kHash) { - if (uint256::size() != specifier.hash().size()) + if (auto hash = uint256::fromVoidChecked(specifier.hash())) + { + ledger = *hash; + } + else { grpc::Status errorStatus{ grpc::StatusCode::INVALID_ARGUMENT, "ledger hash malformed"}; return errorStatus; } - ledger = uint256::fromVoid(specifier.hash().data()); } return ledger; } diff --git a/src/ripple/rpc/handlers/LedgerData.cpp b/src/ripple/rpc/handlers/LedgerData.cpp index 14fe985dcc..fbc17b75b7 100644 --- a/src/ripple/rpc/handlers/LedgerData.cpp +++ b/src/ripple/rpc/handlers/LedgerData.cpp @@ -137,42 +137,49 @@ doLedgerDataGrpc( grpc::Status status = grpc::Status::OK; std::shared_ptr ledger; - if (RPC::ledgerFromRequest(ledger, context)) + if (auto status = RPC::ledgerFromRequest(ledger, context)) { - grpc::Status errorStatus{ - grpc::StatusCode::NOT_FOUND, "ledger not found"}; + grpc::Status errorStatus; + if (status.toErrorCode() == rpcINVALID_PARAMS) + { + errorStatus = grpc::Status( + grpc::StatusCode::INVALID_ARGUMENT, status.message()); + } + else + { + errorStatus = + grpc::Status(grpc::StatusCode::NOT_FOUND, status.message()); + } return {response, errorStatus}; } - ReadView::key_type key = ReadView::key_type(); - if (request.marker().size() != 0) + uint256 startKey; + if (auto key = uint256::fromVoidChecked(request.marker())) { - key = uint256::fromVoid(request.marker().data()); - if (key.size() != request.marker().size()) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, "marker malformed"}; - return {response, errorStatus}; - } + startKey = *key; + } + else if (request.marker().size() != 0) + { + grpc::Status errorStatus{ + grpc::StatusCode::INVALID_ARGUMENT, "marker malformed"}; + return {response, errorStatus}; } auto e = ledger->sles.end(); - ReadView::key_type stopKey = ReadView::key_type(); - if (request.end_marker().size() != 0) + if (auto key = uint256::fromVoidChecked(request.end_marker())) { - stopKey = uint256::fromVoid(request.end_marker().data()); - if (stopKey.size() != request.marker().size()) - { - grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, "end marker malformed"}; - return {response, errorStatus}; - } - e = ledger->sles.upper_bound(stopKey); + e = ledger->sles.upper_bound(*key); + } + else if (request.end_marker().size() != 0) + { + grpc::Status errorStatus{ + grpc::StatusCode::INVALID_ARGUMENT, "end marker malformed"}; + return {response, errorStatus}; } int maxLimit = RPC::Tuning::pageLength(true); - for (auto i = ledger->sles.upper_bound(key); i != e; ++i) + for (auto i = ledger->sles.upper_bound(startKey); i != e; ++i) { auto sle = ledger->read(keylet::unchecked((*i)->key())); if (maxLimit-- <= 0) diff --git a/src/ripple/rpc/handlers/LedgerEntry.cpp b/src/ripple/rpc/handlers/LedgerEntry.cpp index a4c78b3bbf..12696abb3f 100644 --- a/src/ripple/rpc/handlers/LedgerEntry.cpp +++ b/src/ripple/rpc/handlers/LedgerEntry.cpp @@ -377,23 +377,31 @@ doLedgerEntryGrpc( grpc::Status status = grpc::Status::OK; std::shared_ptr ledger; - if (RPC::ledgerFromRequest(ledger, context)) + if (auto status = RPC::ledgerFromRequest(ledger, context)) { - grpc::Status errorStatus{ - grpc::StatusCode::NOT_FOUND, "ledger not found"}; + grpc::Status errorStatus; + if (status.toErrorCode() == rpcINVALID_PARAMS) + { + errorStatus = grpc::Status( + grpc::StatusCode::INVALID_ARGUMENT, status.message()); + } + else + { + errorStatus = + grpc::Status(grpc::StatusCode::NOT_FOUND, status.message()); + } return {response, errorStatus}; } - std::string const& keyBytes = request.key(); - auto key = uint256::fromVoid(keyBytes.data()); - if (keyBytes.size() != key.size()) + auto key = uint256::fromVoidChecked(request.key()); + if (!key) { grpc::Status errorStatus{ grpc::StatusCode::INVALID_ARGUMENT, "index malformed"}; return {response, errorStatus}; } - auto const sleNode = ledger->read(keylet::unchecked(key)); + auto const sleNode = ledger->read(keylet::unchecked(*key)); if (!sleNode) { grpc::Status errorStatus{ diff --git a/src/ripple/rpc/handlers/LedgerHandler.cpp b/src/ripple/rpc/handlers/LedgerHandler.cpp index cab3e605ee..6e01fa94fc 100644 --- a/src/ripple/rpc/handlers/LedgerHandler.cpp +++ b/src/ripple/rpc/handlers/LedgerHandler.cpp @@ -110,10 +110,19 @@ doLedgerGrpc(RPC::GRPCContext& context) grpc::Status status = grpc::Status::OK; std::shared_ptr ledger; - if (RPC::ledgerFromRequest(ledger, context)) + if (auto status = RPC::ledgerFromRequest(ledger, context)) { - grpc::Status errorStatus{ - grpc::StatusCode::NOT_FOUND, "ledger not found"}; + grpc::Status errorStatus; + if (status.toErrorCode() == rpcINVALID_PARAMS) + { + errorStatus = grpc::Status( + grpc::StatusCode::INVALID_ARGUMENT, status.message()); + } + else + { + errorStatus = + grpc::Status(grpc::StatusCode::NOT_FOUND, status.message()); + } return {response, errorStatus}; } diff --git a/src/ripple/rpc/handlers/Tx.cpp b/src/ripple/rpc/handlers/Tx.cpp index 049ed81934..aa941d795c 100644 --- a/src/ripple/rpc/handlers/Tx.cpp +++ b/src/ripple/rpc/handlers/Tx.cpp @@ -456,12 +456,14 @@ doTxGrpc(RPC::GRPCContext& context) TxArgs args; - std::string const& hashBytes = request.hash(); - args.hash = uint256::fromVoid(hashBytes.data()); - if (args.hash.size() != hashBytes.size()) + if (auto hash = uint256::fromVoidChecked(request.hash())) + { + args.hash = *hash; + } + else { grpc::Status errorStatus{ - grpc::StatusCode::INVALID_ARGUMENT, "ledger hash malformed"}; + grpc::StatusCode::INVALID_ARGUMENT, "tx hash malformed"}; return {response, errorStatus}; } diff --git a/src/ripple/rpc/impl/RPCHelpers.cpp b/src/ripple/rpc/impl/RPCHelpers.cpp index c3b3e89d79..be1d005a38 100644 --- a/src/ripple/rpc/impl/RPCHelpers.cpp +++ b/src/ripple/rpc/impl/RPCHelpers.cpp @@ -294,8 +294,11 @@ ledgerFromSpecifier( switch (ledgerCase) { case LedgerCase::kHash: { - uint256 ledgerHash = uint256::fromVoid(specifier.hash().data()); - return getLedger(ledger, ledgerHash, context); + if (auto hash = uint256::fromVoidChecked(specifier.hash())) + { + return getLedger(ledger, *hash, context); + } + return {rpcINVALID_PARAMS, "ledgerHashMalformed"}; } case LedgerCase::kSequence: return getLedger(ledger, specifier.sequence(), context); diff --git a/src/test/rpc/ReportingETL_test.cpp b/src/test/rpc/ReportingETL_test.cpp index a1f2c4f646..8678e2b9be 100644 --- a/src/test/rpc/ReportingETL_test.cpp +++ b/src/test/rpc/ReportingETL_test.cpp @@ -419,6 +419,14 @@ class ReportingETL_test : public beast::unit_test::suite } } + { + auto [status, reply] = + grpcLedgerData(env.closed()->seq(), "bad marker"); + BEAST_EXPECT(!status.ok()); + BEAST_EXPECT( + status.error_code() == grpc::StatusCode::INVALID_ARGUMENT); + } + num_accounts = 3000; for (auto i = 0; i < num_accounts; i++)