Skip to content

Commit 8127654

Browse files
committed
Merge bitcoin/bitcoin#30148: cli: restrict multiple exclusive argument usage in bitcoin-cli
c8e6771 test: restrict multiple CLI arguments (naiyoma) 8838c4f common/args.h: automate check for multiple cli commands (naiyoma) Pull request description: This PR is a continuation of the validation suggested [here](bitcoin/bitcoin#27815) to ensure that only one Request Handler can be specified at a time. ACKs for top commit: stratospher: reACK c8e6771. achow101: ACK c8e6771 tdb3: cr re ACK c8e6771 Tree-SHA512: f4fe036fee342a54f1a7ac702ac35c40bf3d420fde6ab16313a75327292d5ee5c8ece1be9f852a13fcf73da1148b143b37b4894e294052abdde6eefb2e8c6f3f
2 parents 210210c + c8e6771 commit 8127654

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

src/bitcoin-cli.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,10 @@ static void SetupCliArgs(ArgsManager& argsman)
8787
"arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to "
8888
"RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000",
8989
DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES),
90-
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
91-
argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total, after filtering for quality and recency. The total number of addresses known to the node may be higher.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
92-
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
93-
argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0). Pass \"help\" for detailed help documentation.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
90+
ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
91+
argsman.AddArg("-addrinfo", "Get the number of addresses known to the node, per network and total, after filtering for quality and recency. The total number of addresses known to the node may be higher.", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
92+
argsman.AddArg("-getinfo", "Get general information from the remote server. Note that unlike server-side RPC calls, the output of -getinfo is the result of multiple non-atomic requests. Some entries in the output may represent results from different states (e.g. wallet balance may be as of a different block from the chain state reported)", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
93+
argsman.AddArg("-netinfo", "Get network peer connection information from the remote server. An optional integer argument from 0 to 4 can be passed for different peers listings (default: 0). Pass \"help\" for detailed help documentation.", ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
9494

9595
SetupChainParamsBaseOptions(argsman);
9696
argsman.AddArg("-color=<when>", strprintf("Color setting for CLI output (default: %s). Valid values: always, auto (add color codes when standard output is connected to a terminal and OS is not WIN32), never.", DEFAULT_COLOR_SETTING), ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
@@ -1212,6 +1212,7 @@ static int CommandLineRPC(int argc, char *argv[])
12121212
fputc('\n', stdout);
12131213
}
12141214
}
1215+
gArgs.CheckMultipleCLIArgs();
12151216
std::unique_ptr<BaseRequestHandler> rh;
12161217
std::string method;
12171218
if (gArgs.IsArgSet("-getinfo")) {

src/common/args.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <util/fs.h>
1717
#include <util/fs_helpers.h>
1818
#include <util/strencodings.h>
19+
#include <util/string.h>
1920

2021
#ifdef WIN32
2122
#include <codecvt> /* for codecvt_utf8_utf16 */
@@ -588,6 +589,23 @@ void ArgsManager::AddHiddenArgs(const std::vector<std::string>& names)
588589
}
589590
}
590591

592+
void ArgsManager::CheckMultipleCLIArgs() const
593+
{
594+
LOCK(cs_args);
595+
std::vector<std::string> found{};
596+
auto cmds = m_available_args.find(OptionsCategory::CLI_COMMANDS);
597+
if (cmds != m_available_args.end()) {
598+
for (const auto& [cmd, argspec] : cmds->second) {
599+
if (IsArgSet(cmd)) {
600+
found.push_back(cmd);
601+
}
602+
}
603+
if (found.size() > 1) {
604+
throw std::runtime_error(strprintf("Only one of %s may be specified.", util::Join(found, ", ")));
605+
}
606+
}
607+
}
608+
591609
std::string ArgsManager::GetHelpMessage() const
592610
{
593611
const bool show_debug = GetBoolArg("-help-debug", false);
@@ -635,6 +653,9 @@ std::string ArgsManager::GetHelpMessage() const
635653
case OptionsCategory::REGISTER_COMMANDS:
636654
usage += HelpMessageGroup("Register Commands:");
637655
break;
656+
case OptionsCategory::CLI_COMMANDS:
657+
usage += HelpMessageGroup("CLI Commands:");
658+
break;
638659
default:
639660
break;
640661
}

src/common/args.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ enum class OptionsCategory {
6363
GUI,
6464
COMMANDS,
6565
REGISTER_COMMANDS,
66+
CLI_COMMANDS,
6667

6768
HIDDEN // Always the last option to avoid printing these in the help
6869
};
@@ -363,6 +364,13 @@ class ArgsManager
363364
m_network_only_args.clear();
364365
}
365366

367+
/**
368+
* Check CLI command args
369+
*
370+
* @throws std::runtime_error when multiple CLI_COMMAND arguments are specified
371+
*/
372+
void CheckMultipleCLIArgs() const;
373+
366374
/**
367375
* Get the help string
368376
*/

src/test/fuzz/system.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ FUZZ_TARGET(system, .init = initialize_system)
5353
args_manager.SoftSetBoolArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeBool());
5454
},
5555
[&] {
56-
const OptionsCategory options_category = fuzzed_data_provider.PickValueInArray<OptionsCategory>({OptionsCategory::OPTIONS, OptionsCategory::CONNECTION, OptionsCategory::WALLET, OptionsCategory::WALLET_DEBUG_TEST, OptionsCategory::ZMQ, OptionsCategory::DEBUG_TEST, OptionsCategory::CHAINPARAMS, OptionsCategory::NODE_RELAY, OptionsCategory::BLOCK_CREATION, OptionsCategory::RPC, OptionsCategory::GUI, OptionsCategory::COMMANDS, OptionsCategory::REGISTER_COMMANDS, OptionsCategory::HIDDEN});
56+
const OptionsCategory options_category = fuzzed_data_provider.PickValueInArray<OptionsCategory>({OptionsCategory::OPTIONS, OptionsCategory::CONNECTION, OptionsCategory::WALLET, OptionsCategory::WALLET_DEBUG_TEST, OptionsCategory::ZMQ, OptionsCategory::DEBUG_TEST, OptionsCategory::CHAINPARAMS, OptionsCategory::NODE_RELAY, OptionsCategory::BLOCK_CREATION, OptionsCategory::RPC, OptionsCategory::GUI, OptionsCategory::COMMANDS, OptionsCategory::REGISTER_COMMANDS, OptionsCategory::CLI_COMMANDS, OptionsCategory::HIDDEN});
5757
// Avoid hitting:
5858
// common/args.cpp:563: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
5959
const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));

test/functional/interface_bitcoin_cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,9 @@ def run_test(self):
381381
assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcwait', '-rpcwaittimeout=5').echo)
382382
assert_greater_than_or_equal(time.time(), start_time + 5)
383383

384+
self.log.info("Test that only one of -addrinfo, -generate, -getinfo, -netinfo may be specified at a time")
385+
assert_raises_process_error(1, "Only one of -getinfo, -netinfo may be specified", self.nodes[0].cli('-getinfo', '-netinfo').send_cli)
386+
384387

385388
if __name__ == '__main__':
386389
TestBitcoinCli(__file__).main()

0 commit comments

Comments
 (0)