aboutsummaryrefslogtreecommitdiff
path: root/src/rpc/util.cpp
diff options
context:
space:
mode:
authorMarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>2022-12-12 14:30:14 +0100
committerMarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>2023-01-11 17:42:09 +0100
commitfa9f6d7bcdba5f18c46fff1dcc0ac6d3dd8db75d (patch)
tree31a0e2c31f826a40fa74e03fe530cdb00dcf5559 /src/rpc/util.cpp
parentfaf96721a66dcc215ea9d6affb30f9a00cc37000 (diff)
rpc: Run type check against RPCArgs
Diffstat (limited to 'src/rpc/util.cpp')
-rw-r--r--src/rpc/util.cpp58
1 files changed, 41 insertions, 17 deletions
diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp
index 53785b1941..bb850a9171 100644
--- a/src/rpc/util.cpp
+++ b/src/rpc/util.cpp
@@ -30,23 +30,6 @@ std::string GetAllOutputTypes()
return Join(ret, ", ");
}
-void RPCTypeCheck(const UniValue& params,
- const std::list<UniValueType>& typesExpected,
- bool fAllowNull)
-{
- unsigned int i = 0;
- for (const UniValueType& t : typesExpected) {
- if (params.size() <= i)
- break;
-
- const UniValue& v = params[i];
- if (!(fAllowNull && v.isNull())) {
- RPCTypeCheckArgument(v, t);
- }
- i++;
- }
-}
-
void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected)
{
if (!typeExpected.typeAny && value.type() != typeExpected.type) {
@@ -579,6 +562,9 @@ UniValue RPCHelpMan::HandleRequest(const JSONRPCRequest& request) const
if (request.mode == JSONRPCRequest::GET_HELP || !IsValidNumArgs(request.params.size())) {
throw std::runtime_error(ToString());
}
+ for (size_t i{0}; i < m_args.size(); ++i) {
+ m_args.at(i).MatchesType(request.params[i]);
+ }
UniValue ret = m_fun(*this, request);
if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
CHECK_NONFATAL(std::any_of(m_results.m_results.begin(), m_results.m_results.end(), [&ret](const RPCResult& res) { return res.MatchesType(ret); }));
@@ -677,6 +663,44 @@ UniValue RPCHelpMan::GetArgMap() const
return arr;
}
+void RPCArg::MatchesType(const UniValue& request) const
+{
+ if (m_opts.skip_type_check) return;
+ if (IsOptional() && request.isNull()) return;
+ switch (m_type) {
+ case Type::STR_HEX:
+ case Type::STR: {
+ RPCTypeCheckArgument(request, UniValue::VSTR);
+ return;
+ }
+ case Type::NUM: {
+ RPCTypeCheckArgument(request, UniValue::VNUM);
+ return;
+ }
+ case Type::AMOUNT: {
+ // VNUM or VSTR, checked inside AmountFromValue()
+ return;
+ }
+ case Type::RANGE: {
+ // VNUM or VARR, checked inside ParseRange()
+ return;
+ }
+ case Type::BOOL: {
+ RPCTypeCheckArgument(request, UniValue::VBOOL);
+ return;
+ }
+ case Type::OBJ:
+ case Type::OBJ_USER_KEYS: {
+ RPCTypeCheckArgument(request, UniValue::VOBJ);
+ return;
+ }
+ case Type::ARR: {
+ RPCTypeCheckArgument(request, UniValue::VARR);
+ return;
+ }
+ } // no default case, so the compiler can warn about missing cases
+}
+
std::string RPCArg::GetFirstName() const
{
return m_names.substr(0, m_names.find("|"));