Skip to content

Commit 1a8a5ed

Browse files
committed
Merge #15401: rpc: Actually throw help when passed invalid number of params
fa4ce70 rpc: Actually throw help when passed invalid number of params (MarcoFalke) fa05626 rpc: Add RPCHelpMan::IsValidNumArgs() (MarcoFalke) Pull request description: Can be tested by * running the included test against an old binary (compiled without this patch) * calling `setban 1 "add" 3 4 5 6 7 8 9 0` in the gui Tree-SHA512: aa6a25bbe6f40722913ea292252a62a4012c964eed9f4035335a2e2d13be98eb60f368e8a3251a104a26a62c08b2cb926b06e5ab1418ef1cf4abdd71d87c2919
2 parents f3f9c1d + fa4ce70 commit 1a8a5ed

File tree

5 files changed

+46
-22
lines changed

5 files changed

+46
-22
lines changed

src/rpc/blockchain.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2010 Satoshi Nakamoto
2-
// Copyright (c) 2009-2018 The Bitcoin Core developers
2+
// Copyright (c) 2009-2019 The Bitcoin Core developers
33
// Distributed under the MIT software license, see the accompanying
44
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

@@ -1778,9 +1778,7 @@ static constexpr size_t PER_UTXO_OVERHEAD = sizeof(COutPoint) + sizeof(uint32_t)
17781778

17791779
static UniValue getblockstats(const JSONRPCRequest& request)
17801780
{
1781-
if (request.fHelp || request.params.size() < 1 || request.params.size() > 4) {
1782-
throw std::runtime_error(
1783-
RPCHelpMan{"getblockstats",
1781+
const RPCHelpMan help{"getblockstats",
17841782
"\nCompute per block statistics for a given window. All amounts are in satoshis.\n"
17851783
"It won't work for some heights with pruning.\n"
17861784
"It won't work without -txindex for utxo_size_inc, *fee or *feerate stats.\n",
@@ -1836,7 +1834,9 @@ static UniValue getblockstats(const JSONRPCRequest& request)
18361834
HelpExampleCli("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
18371835
+ HelpExampleRpc("getblockstats", "1000 '[\"minfeerate\",\"avgfeerate\"]'")
18381836
},
1839-
}.ToString());
1837+
};
1838+
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
1839+
throw std::runtime_error(help.ToString());
18401840
}
18411841

18421842
LOCK(cs_main);

src/rpc/net.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -523,13 +523,7 @@ static UniValue getnetworkinfo(const JSONRPCRequest& request)
523523

524524
static UniValue setban(const JSONRPCRequest& request)
525525
{
526-
std::string strCommand;
527-
if (!request.params[1].isNull())
528-
strCommand = request.params[1].get_str();
529-
if (request.fHelp || request.params.size() < 2 ||
530-
(strCommand != "add" && strCommand != "remove"))
531-
throw std::runtime_error(
532-
RPCHelpMan{"setban",
526+
const RPCHelpMan help{"setban",
533527
"\nAttempts to add or remove an IP/Subnet from the banned list.\n",
534528
{
535529
{"subnet", RPCArg::Type::STR, RPCArg::Optional::NO, "The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)"},
@@ -543,7 +537,13 @@ static UniValue setban(const JSONRPCRequest& request)
543537
+ HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"")
544538
+ HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")
545539
},
546-
}.ToString());
540+
};
541+
std::string strCommand;
542+
if (!request.params[1].isNull())
543+
strCommand = request.params[1].get_str();
544+
if (request.fHelp || !help.IsValidNumArgs(request.params.size()) || (strCommand != "add" && strCommand != "remove")) {
545+
throw std::runtime_error(help.ToString());
546+
}
547547
if (!g_banman) {
548548
throw JSONRPCError(RPC_DATABASE_ERROR, "Error: Ban database not loaded");
549549
}

src/rpc/util.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2017-2018 The Bitcoin Core developers
1+
// Copyright (c) 2017-2019 The Bitcoin Core developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

@@ -314,6 +314,17 @@ std::string RPCExamples::ToDescriptionString() const
314314
return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples;
315315
}
316316

317+
bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
318+
{
319+
size_t num_required_args = 0;
320+
for (size_t n = m_args.size(); n > 0; --n) {
321+
if (!m_args.at(n - 1).IsOptional()) {
322+
num_required_args = n;
323+
break;
324+
}
325+
}
326+
return num_required_args <= num_args && num_args <= m_args.size();
327+
}
317328
std::string RPCHelpMan::ToString() const
318329
{
319330
std::string ret;
@@ -322,12 +333,7 @@ std::string RPCHelpMan::ToString() const
322333
ret += m_name;
323334
bool was_optional{false};
324335
for (const auto& arg : m_args) {
325-
bool optional;
326-
if (arg.m_fallback.which() == 1) {
327-
optional = true;
328-
} else {
329-
optional = RPCArg::Optional::NO != boost::get<RPCArg::Optional>(arg.m_fallback);
330-
}
336+
const bool optional = arg.IsOptional();
331337
ret += " ";
332338
if (optional) {
333339
if (!was_optional) ret += "( ";
@@ -369,6 +375,15 @@ std::string RPCHelpMan::ToString() const
369375
return ret;
370376
}
371377

378+
bool RPCArg::IsOptional() const
379+
{
380+
if (m_fallback.which() == 1) {
381+
return true;
382+
} else {
383+
return RPCArg::Optional::NO != boost::get<RPCArg::Optional>(m_fallback);
384+
}
385+
}
386+
372387
std::string RPCArg::ToDescriptionString() const
373388
{
374389
std::string ret;

src/rpc/util.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2017-2018 The Bitcoin Core developers
1+
// Copyright (c) 2017-2019 The Bitcoin Core developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

@@ -54,7 +54,7 @@ struct RPCArg {
5454
/** Required arg */
5555
NO,
5656
/**
57-
* Optinal arg that is a named argument and has a default value of
57+
* Optional arg that is a named argument and has a default value of
5858
* `null`. When possible, the default value should be specified.
5959
*/
6060
OMITTED_NAMED_ARG,
@@ -111,6 +111,8 @@ struct RPCArg {
111111
assert(type == Type::ARR || type == Type::OBJ);
112112
}
113113

114+
bool IsOptional() const;
115+
114116
/**
115117
* Return the type string of the argument.
116118
* Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).
@@ -186,6 +188,8 @@ class RPCHelpMan
186188
RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples);
187189

188190
std::string ToString() const;
191+
/** If the supplied number of args is neither too small nor too high */
192+
bool IsValidNumArgs(size_t num_args) const;
189193

190194
private:
191195
const std::string m_name;

test/functional/rpc_getblockstats.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,10 @@ def run_test(self):
178178
assert_raises_rpc_error(-5, 'Block not found', self.nodes[0].getblockstats,
179179
hash_or_height='000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f')
180180

181+
# Invalid number of args
182+
assert_raises_rpc_error(-1, 'getblockstats hash_or_height ( stats )', self.nodes[0].getblockstats, '00', 1, 2)
183+
assert_raises_rpc_error(-1, 'getblockstats hash_or_height ( stats )', self.nodes[0].getblockstats)
184+
185+
181186
if __name__ == '__main__':
182187
GetblockstatsTest().main()

0 commit comments

Comments
 (0)