diff --git a/src/test/rpc/RPCCall_test.cpp b/src/test/rpc/RPCCall_test.cpp index 7647dc5f65..f17d87884a 100644 --- a/src/test/rpc/RPCCall_test.cpp +++ b/src/test/rpc/RPCCall_test.cpp @@ -1381,16 +1381,32 @@ static RPCCallTestData const rpcCallTestArray[] = { "account_tx: non-integer min.", __LINE__, {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "Binary", "-1"}, - RPCCallTestData::bad_cast, - R"()", + RPCCallTestData::no_exception, + R"({ + "method" : "account_tx", + "params" : [ + { + "error" : "invalidLgrRange", + "error_message" : "Ledger range is invalid." + } + ] +})", }, { // Note: this really shouldn't throw, but does at the moment. "account_tx: non-integer max.", __LINE__, {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "counts"}, - RPCCallTestData::bad_cast, - R"()", + RPCCallTestData::no_exception, + R"({ + "method" : "account_tx", + "params" : [ + { + "error" : "invalidLgrRange", + "error_message" : "Ledger range is invalid." + } + ] +})", }, { // Note: this really shouldn't throw, but does at the moment. @@ -1400,25 +1416,39 @@ static RPCCallTestData const rpcCallTestArray[] = { "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "-1", - "decending"}, - RPCCallTestData::bad_cast, - R"()", + "200", + "bad_offset"}, + RPCCallTestData::no_exception, + R"({ + "method" : "account_tx", + "params" : [ + { + "error" : "invalidParams", + "error_message" : "Invalid field 'offset'." + } + ] +})", }, { - // Note: this really shouldn't throw, but does at the moment. "account_tx: non-integer limit.", __LINE__, {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "-1", "-1", - "300", - "false"}, - RPCCallTestData::bad_cast, - R"()", + "bad_limit"}, + RPCCallTestData::no_exception, + R"({ + "method" : "account_tx", + "params" : [ + { + "error" : "invalidParams", + "error_message" : "Invalid field 'limit'." + } + ] +})", }, - {// Note: this really shouldn't throw, but does at the moment. - "account_tx: RIPD-1570.", + {"account_tx: RIPD-1570.", __LINE__, {"account_tx", "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", @@ -1428,8 +1458,16 @@ static RPCCallTestData const rpcCallTestArray[] = { "false", "false", "false"}, - RPCCallTestData::bad_cast, - R"()"}, + RPCCallTestData::no_exception, + R"({ + "method" : "account_tx", + "params" : [ + { + "error" : "invalidParams", + "error_message" : "Invalid field 'offset'." + } + ] +})"}, // book_offers // ----------------------------------------------------------------- @@ -5978,6 +6016,10 @@ public: } else { + std::cout << "no match: " << rpcCallTest.description + << std::endl; + std::cout << " got: " << got.toStyledString() << std::endl; + std::cout << " exp: " << exp.toStyledString() << std::endl; fail(rpcCallTest.description, __FILE__, rpcCallTest.line); } } diff --git a/src/xrpld/rpc/detail/RPCCall.cpp b/src/xrpld/rpc/detail/RPCCall.cpp index 185043302a..8ca2548aea 100644 --- a/src/xrpld/rpc/detail/RPCCall.cpp +++ b/src/xrpld/rpc/detail/RPCCall.cpp @@ -135,6 +135,22 @@ private: } } + static std::optional + jvParseInt(Json::Value const& param) + { + if (param.isUInt() || param.isInt()) + return param.asInt(); + + if (param.isString()) + { + std::int32_t v; + if (beast::lexicalCastChecked(v, param.asString())) + return v; + } + + return std::nullopt; + } + static bool validPublicKey( std::string const& strPk, @@ -266,24 +282,50 @@ private: } else { - std::int64_t uLedgerMin = jvParams[1u].asInt(); - std::int64_t uLedgerMax = jvParams[2u].asInt(); + std::int32_t ledgerMin, ledgerMax; + if (auto ledgerMinOpt = jvParseInt(jvParams[1u])) + { + ledgerMin = *ledgerMinOpt; + } + else + { + return rpcError(rpcINVALID_LGR_RANGE); + } - if (uLedgerMax != -1 && uLedgerMax < uLedgerMin) + if (auto ledgerMaxOpt = jvParseInt(jvParams[2u])) + { + ledgerMax = *ledgerMaxOpt; + } + else + { + return rpcError(rpcINVALID_LGR_RANGE); + } + + if (ledgerMax != -1 && ledgerMax < ledgerMin) { if (apiVersion_ == 1) return rpcError(rpcLGR_IDXS_INVALID); return rpcError(rpcNOT_SYNCED); } - jvRequest[jss::ledger_index_min] = jvParams[1u].asInt(); - jvRequest[jss::ledger_index_max] = jvParams[2u].asInt(); + jvRequest[jss::ledger_index_min] = ledgerMin; + jvRequest[jss::ledger_index_max] = ledgerMax; if (iParams >= 4) - jvRequest[jss::limit] = jvParams[3u].asInt(); + { + if (auto limit = jvParseInt(jvParams[3u])) + jvRequest[jss::limit] = *limit; + else + return RPC::invalid_field_error(jss::limit); + } if (iParams >= 5) - jvRequest[jss::offset] = jvParams[4u].asInt(); + { + if (auto offset = jvParseInt(jvParams[4u])) + jvRequest[jss::offset] = *offset; + else + return RPC::invalid_field_error(jss::offset); + } } return jvRequest;