Validate data size before calling uint256::fromVoid

This commit is contained in:
CJ Cobb
2021-08-05 15:58:30 -04:00
committed by Nik Bougalis
parent 15b0ae5bf0
commit 3fb60a89a3
10 changed files with 106 additions and 51 deletions

View File

@@ -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> sle = std::make_shared<SLE>(it, key);
std::shared_ptr<SLE> sle = std::make_shared<SLE>(it, *key);
queue.push(sle);
}

View File

@@ -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> sle = std::make_shared<SLE>(it, key);
std::shared_ptr<SLE> sle = std::make_shared<SLE>(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);
}
}

View File

@@ -313,6 +313,15 @@ public:
return base_uint(data, VoidHelper());
}
template <class T>
static std::optional<base_uint>
fromVoidChecked(T const& from)
{
if (from.size() != size())
return {};
return fromVoid(from.data());
}
constexpr int
signum() const
{

View File

@@ -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;
}

View File

@@ -137,42 +137,49 @@ doLedgerDataGrpc(
grpc::Status status = grpc::Status::OK;
std::shared_ptr<ReadView const> 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)

View File

@@ -377,23 +377,31 @@ doLedgerEntryGrpc(
grpc::Status status = grpc::Status::OK;
std::shared_ptr<ReadView const> 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{

View File

@@ -110,10 +110,19 @@ doLedgerGrpc(RPC::GRPCContext<org::xrpl::rpc::v1::GetLedgerRequest>& context)
grpc::Status status = grpc::Status::OK;
std::shared_ptr<ReadView const> 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};
}

View File

@@ -456,12 +456,14 @@ doTxGrpc(RPC::GRPCContext<org::xrpl::rpc::v1::GetTransactionRequest>& 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};
}

View File

@@ -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);

View File

@@ -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++)