Skip to content

Commit fabf051

Browse files
author
MarcoFalke
committed
rpc: Fail to return undocumented return values
1 parent 1e57d14 commit fabf051

File tree

5 files changed

+51
-9
lines changed

5 files changed

+51
-9
lines changed

src/qt/test/rpcnestedtests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static RPCHelpMan rpcNestedTest_rpc()
2424
{"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
2525
{"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, ""},
2626
},
27-
{},
27+
RPCResult{RPCResult::Type::ANY, "", ""},
2828
RPCExamples{""},
2929
[](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
3030
return request.params.write(0, 0);

src/rpc/misc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ static RPCHelpMan echo(const std::string& name)
628628
{"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
629629
{"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, ""},
630630
},
631-
RPCResult{RPCResult::Type::NONE, "", "Returns whatever was passed in"},
631+
RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
632632
RPCExamples{""},
633633
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
634634
{

src/rpc/server.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ static RPCHelpMan help()
149149
}
150150
if (strCommand == "dump_all_command_conversions") {
151151
// Used for testing only, undocumented
152+
const_cast<JSONRPCRequest&>(jsonRequest).mode = JSONRPCRequest::GET_ARGS;
152153
return tableRPC.dumpArgMap(jsonRequest);
153154
}
154155

@@ -492,11 +493,8 @@ std::vector<std::string> CRPCTable::listCommands() const
492493
return commandList;
493494
}
494495

495-
UniValue CRPCTable::dumpArgMap(const JSONRPCRequest& args_request) const
496+
UniValue CRPCTable::dumpArgMap(const JSONRPCRequest& request) const
496497
{
497-
JSONRPCRequest request(args_request);
498-
request.mode = JSONRPCRequest::GET_ARGS;
499-
500498
UniValue ret{UniValue::VARR};
501499
for (const auto& cmd : mapCommands) {
502500
UniValue result;

src/rpc/util.cpp

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ std::string RPCExamples::ToDescriptionString() const
459459
return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples;
460460
}
461461

462-
UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request)
462+
UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
463463
{
464464
if (request.mode == JSONRPCRequest::GET_ARGS) {
465465
return GetArgMap();
@@ -471,7 +471,11 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request)
471471
if (request.mode == JSONRPCRequest::GET_HELP || !IsValidNumArgs(request.params.size())) {
472472
throw std::runtime_error(ToString());
473473
}
474-
return m_fun(*this, request);
474+
const UniValue ret = m_fun(*this, request);
475+
if (request.mode != JSONRPCRequest::GET_ARGS) {
476+
CHECK_NONFATAL(std::any_of(m_results.m_results.begin(), m_results.m_results.end(), [ret](const RPCResult& res) { return res.MatchesType(ret); }));
477+
}
478+
return ret;
475479
}
476480

477481
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
@@ -677,6 +681,7 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const
677681
sections.PushSection({indent + "..." + maybe_separator, m_description});
678682
return;
679683
}
684+
case Type::ANY:
680685
case Type::NONE: {
681686
sections.PushSection({indent + "null" + maybe_separator, Description("json null")});
682687
return;
@@ -742,6 +747,42 @@ void RPCResult::ToSections(Sections& sections, const OuterType outer_type, const
742747
CHECK_NONFATAL(false);
743748
}
744749

750+
bool RPCResult::MatchesType(const UniValue& result) const
751+
{
752+
switch (m_type) {
753+
case Type::ELISION: {
754+
return false;
755+
}
756+
case Type::ANY: {
757+
return true;
758+
}
759+
case Type::NONE: {
760+
return UniValue::VNULL == result.getType();
761+
}
762+
case Type::STR:
763+
case Type::STR_HEX: {
764+
return UniValue::VSTR == result.getType();
765+
}
766+
case Type::NUM:
767+
case Type::STR_AMOUNT:
768+
case Type::NUM_TIME: {
769+
return UniValue::VNUM == result.getType();
770+
}
771+
case Type::BOOL: {
772+
return UniValue::VBOOL == result.getType();
773+
}
774+
case Type::ARR_FIXED:
775+
case Type::ARR: {
776+
return UniValue::VARR == result.getType();
777+
}
778+
case Type::OBJ_DYN:
779+
case Type::OBJ: {
780+
return UniValue::VOBJ == result.getType();
781+
}
782+
} // no default case, so the compiler can warn about missing cases
783+
CHECK_NONFATAL(false);
784+
}
785+
745786
std::string RPCArg::ToStringObj(const bool oneline) const
746787
{
747788
std::string res;

src/rpc/util.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ struct RPCResult {
223223
NUM,
224224
BOOL,
225225
NONE,
226+
ANY, //!< Special type to disable type checks (for testing only)
226227
STR_AMOUNT, //!< Special string to represent a floating point amount
227228
STR_HEX, //!< Special string with only hex chars
228229
OBJ_DYN, //!< Special dictionary with keys that are not literals
@@ -295,6 +296,8 @@ struct RPCResult {
295296
std::string ToStringObj() const;
296297
/** Return the description string, including the result type. */
297298
std::string ToDescriptionString() const;
299+
/** Check whether the result JSON type matches. */
300+
bool MatchesType(const UniValue& result) const;
298301
};
299302

300303
struct RPCResults {
@@ -333,7 +336,7 @@ class RPCHelpMan
333336
using RPCMethodImpl = std::function<UniValue(const RPCHelpMan&, const JSONRPCRequest&)>;
334337
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
335338

336-
UniValue HandleRequest(const JSONRPCRequest& request);
339+
UniValue HandleRequest(const JSONRPCRequest& request) const;
337340
std::string ToString() const;
338341
/** Return the named args that need to be converted from string to another JSON type */
339342
UniValue GetArgMap() const;

0 commit comments

Comments
 (0)