diff --git a/src/ripple/net/impl/RPCCall.cpp b/src/ripple/net/impl/RPCCall.cpp index c392fb46a..741240db8 100644 --- a/src/ripple/net/impl/RPCCall.cpp +++ b/src/ripple/net/impl/RPCCall.cpp @@ -1197,6 +1197,15 @@ std::string JSONRPCRequest (std::string const& strMethod, Json::Value const& par return to_string (request) + "\n"; } +namespace +{ + // Special local exception type thrown when request can't be parsed. + class RequestNotParseable : public std::runtime_error + { + using std::runtime_error::runtime_error; // Inherit constructors + }; +}; + struct RPCCallImp { // VFALCO NOTE Is this a to-do comment or a doc comment? @@ -1228,7 +1237,8 @@ struct RPCCallImp // Parse reply JLOG (j.debug()) << "RPC reply: " << strData << std::endl; - + if (strData.find("Unable to parse request") == 0) + Throw (strData); Json::Reader reader; Json::Value jvReply; if (!reader.parse (strData, jvReply)) @@ -1440,6 +1450,12 @@ rpcClient(std::vector const& args, // YYY We could have a command line flag for single line output for scripts. // YYY We would intercept output here and simplify it. } + catch (RequestNotParseable& e) + { + jvOutput = rpcError(rpcINVALID_PARAMS); + jvOutput["error_what"] = e.what(); + nRet = rpcINVALID_PARAMS; + } catch (std::exception& e) { jvOutput = rpcError (rpcINTERNAL); diff --git a/src/ripple/rpc/impl/ServerHandlerImp.cpp b/src/ripple/rpc/impl/ServerHandlerImp.cpp index 796b0a8a6..ae484b02e 100644 --- a/src/ripple/rpc/impl/ServerHandlerImp.cpp +++ b/src/ripple/rpc/impl/ServerHandlerImp.cpp @@ -569,7 +569,8 @@ ServerHandlerImp::processRequest (Port const& port, ! jsonOrig || ! (jsonOrig.isObject () || jsonOrig.isArray())) { - HTTPReply (400, "Unable to parse request", output, rpcJ); + HTTPReply (400, "Unable to parse request: " + + reader.getFormatedErrorMessages(), output, rpcJ); return; } } diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 3c74ceb59..3f28b079b 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -121,6 +121,20 @@ class LedgerRPC_test : public beast::unit_test::suite checkErrorValue(jrr, "invalidParams", "Invalid parameters."); } + { + // Request a ledger with a very large (double) sequence. + auto const ret = env.rpc ( + "json", "ledger", "{ \"ledger_index\" : 2e15 }"); + BEAST_EXPECT (RPC::contains_error(ret)); + BEAST_EXPECT (ret[jss::error_message] == "Invalid parameters."); + } + + { + // Request a ledger with very large (integer) sequence. + auto const ret = env.rpc ( + "json", "ledger", "{ \"ledger_index\" : 1000000000000000 }"); + checkErrorValue(ret, "invalidParams", "Invalid parameters."); + } } void testLedgerCurrent() diff --git a/src/test/server/ServerStatus_test.cpp b/src/test/server/ServerStatus_test.cpp index 6a48d796c..ea89db89a 100644 --- a/src/test/server/ServerStatus_test.cpp +++ b/src/test/server/ServerStatus_test.cpp @@ -893,7 +893,7 @@ class ServerStatus_test : boost::beast::http::response resp; doHTTPRequest(env, yield, false, resp, ec, "{}"); BEAST_EXPECT(resp.result() == boost::beast::http::status::bad_request); - BEAST_EXPECT(resp.body() == "Unable to parse request\r\n"); + BEAST_EXPECT(resp.body() == "Unable to parse request: \r\n"); } Json::Value jv;