Compare commits

...

3 Commits

Author SHA1 Message Date
Ayaz Salikhov
adbeb94c2b ci: Only upload artifacts in XRPLF repo owner (#6060)
This change prevents uploading too many artifacts in non-public repositories.
2025-11-20 18:09:03 +00:00
Mayukha Vadari
a3d4be4eaf fix: Set correct index for limit in book_offers CLI (#6043)
This change fixes an indexing typo in the `book_offers` CLI processing, and does not affect the HTTPS/WS RPC processing.
2025-11-20 06:37:28 -05:00
Olek
6ff495fd9b Fix: Perform array size check (#6030)
The `ledger_entry` and `deposit_preauth` requests require an array of credentials. However, the array size is not checked before is gets processing. This fix adds checks and return errors in case array size is too big.
2025-11-19 16:58:18 +00:00
5 changed files with 61 additions and 28 deletions

View File

@@ -130,7 +130,7 @@ jobs:
--target "${CMAKE_TARGET}"
- name: Upload rippled artifact (Linux)
if: ${{ runner.os == 'Linux' }}
if: ${{ github.repository_owner == 'XRPLF' && runner.os == 'Linux' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
env:
BUILD_DIR: ${{ inputs.build_dir }}

View File

@@ -1103,7 +1103,7 @@ class LedgerEntry_test : public beast::unit_test::suite
checkErrorValue(
jrr[jss::result],
"malformedAuthorizedCredentials",
"Invalid field 'authorized_credentials', not array.");
"Invalid field 'authorized_credentials', array empty.");
}
{
@@ -1144,7 +1144,7 @@ class LedgerEntry_test : public beast::unit_test::suite
checkErrorValue(
jrr[jss::result],
"malformedAuthorizedCredentials",
"Invalid field 'authorized_credentials', not array.");
"Invalid field 'authorized_credentials', array too long.");
}
}

View File

@@ -1584,8 +1584,6 @@ static RPCCallTestData const rpcCallTestArray[] = {
"EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
"junk", // Note: indexing bug in parseBookOffers() requires junk
// param.
"200",
},
RPCCallTestData::no_exception,
@@ -1597,7 +1595,6 @@ static RPCCallTestData const rpcCallTestArray[] = {
"issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"ledger_hash" : "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
"limit" : 200,
"proof" : true,
"taker_gets" : {
"currency" : "EUR",
"issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"
@@ -1617,8 +1614,8 @@ static RPCCallTestData const rpcCallTestArray[] = {
"EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
"junk", // Note: indexing bug in parseBookOffers() requires junk param.
"200",
"0",
"MyMarker"},
RPCCallTestData::no_exception,
R"({
@@ -1630,7 +1627,6 @@ static RPCCallTestData const rpcCallTestArray[] = {
"ledger_hash" : "ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
"limit" : 200,
"marker" : "MyMarker",
"proof" : true,
"taker_gets" : {
"currency" : "EUR",
"issuer" : "rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA"
@@ -1665,8 +1661,8 @@ static RPCCallTestData const rpcCallTestArray[] = {
"EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
"junk", // Note: indexing bug in parseBookOffers() requires junk param.
"200",
"0",
"MyMarker",
"extra"},
RPCCallTestData::no_exception,
@@ -1770,12 +1766,19 @@ static RPCCallTestData const rpcCallTestArray[] = {
"EUR/rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"rnUy2SHTrB9DubsPmkJZUXTf5FcNDGrYEA",
"ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789",
"junk", // Note: indexing bug in parseBookOffers() requires junk
// param.
"not_a_number",
},
RPCCallTestData::bad_cast,
R"()"},
RPCCallTestData::no_exception,
R"({
"method" : "book_offers",
"params" : [
{
"error" : "invalidParams",
"error_code" : 31,
"error_message" : "Invalid field 'limit'."
}
]
})"},
// can_delete
// ------------------------------------------------------------------

View File

@@ -332,16 +332,32 @@ private:
if (jvParams.size() >= 5)
{
int iLimit = jvParams[5u].asInt();
try
{
int iLimit = jvParams[4u].asInt();
if (iLimit > 0)
jvRequest[jss::limit] = iLimit;
}
if (jvParams.size() >= 6 && jvParams[5u].asInt())
catch (std::exception const&)
{
return RPC::invalid_field_error(jss::limit);
}
}
if (jvParams.size() >= 6)
{
try
{
int bProof = jvParams[5u].asInt();
if (bProof)
jvRequest[jss::proof] = true;
}
catch (std::exception const&)
{
return RPC::invalid_field_error(jss::proof);
}
}
if (jvParams.size() == 7)
jvRequest[jss::marker] = jvParams[6u];

View File

@@ -16,8 +16,6 @@
#include <xrpl/protocol/STXChainBridge.h>
#include <xrpl/protocol/jss.h>
#include <functional>
namespace ripple {
static Expected<uint256, Json::Value>
@@ -178,18 +176,41 @@ static Expected<STArray, Json::Value>
parseAuthorizeCredentials(Json::Value const& jv)
{
if (!jv.isArray())
{
return LedgerEntryHelpers::invalidFieldError(
"malformedAuthorizedCredentials",
jss::authorized_credentials,
"array");
STArray arr(sfAuthorizeCredentials, jv.size());
}
std::uint32_t const n = jv.size();
if (n > maxCredentialsArraySize)
{
return Unexpected(LedgerEntryHelpers::malformedError(
"malformedAuthorizedCredentials",
"Invalid field '" + std::string(jss::authorized_credentials) +
"', array too long."));
}
if (n == 0)
{
return Unexpected(LedgerEntryHelpers::malformedError(
"malformedAuthorizedCredentials",
"Invalid field '" + std::string(jss::authorized_credentials) +
"', array empty."));
}
STArray arr(sfAuthorizeCredentials, n);
for (auto const& jo : jv)
{
if (!jo.isObject())
{
return LedgerEntryHelpers::invalidFieldError(
"malformedAuthorizedCredentials",
jss::authorized_credentials,
"array");
}
if (auto const value = LedgerEntryHelpers::hasRequired(
jo,
{jss::issuer, jss::credential_type},
@@ -260,13 +281,6 @@ parseDepositPreauth(Json::Value const& dp, Json::StaticString const fieldName)
auto const arr = parseAuthorizeCredentials(ac);
if (!arr.has_value())
return Unexpected(arr.error());
if (arr->empty() || (arr->size() > maxCredentialsArraySize))
{
return LedgerEntryHelpers::invalidFieldError(
"malformedAuthorizedCredentials",
jss::authorized_credentials,
"array");
}
auto const& sorted = credentials::makeSorted(arr.value());
if (sorted.empty())