Skip to content

Commit

Permalink
Merge bitcoin/bitcoin#30148: cli: restrict multiple exclusive argumen…
Browse files Browse the repository at this point in the history
…t 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
  • Loading branch information
achow101 committed Sep 4, 2024
2 parents 210210c + c8e6771 commit 8127654
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 5 deletions.
9 changes: 5 additions & 4 deletions src/bitcoin-cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ static void SetupCliArgs(ArgsManager& argsman)
"arguments are number of blocks to generate (default: %s) and maximum iterations to try (default: %s), equivalent to "
"RPC generatetoaddress nblocks and maxtries arguments. Example: bitcoin-cli -generate 4 1000",
DEFAULT_NBLOCKS, DEFAULT_MAX_TRIES),
ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
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);
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);
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);
ArgsManager::ALLOW_ANY, OptionsCategory::CLI_COMMANDS);
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);
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);
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);

SetupChainParamsBaseOptions(argsman);
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);
Expand Down Expand Up @@ -1212,6 +1212,7 @@ static int CommandLineRPC(int argc, char *argv[])
fputc('\n', stdout);
}
}
gArgs.CheckMultipleCLIArgs();
std::unique_ptr<BaseRequestHandler> rh;
std::string method;
if (gArgs.IsArgSet("-getinfo")) {
Expand Down
21 changes: 21 additions & 0 deletions src/common/args.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <util/fs.h>
#include <util/fs_helpers.h>
#include <util/strencodings.h>
#include <util/string.h>

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

void ArgsManager::CheckMultipleCLIArgs() const
{
LOCK(cs_args);
std::vector<std::string> found{};
auto cmds = m_available_args.find(OptionsCategory::CLI_COMMANDS);
if (cmds != m_available_args.end()) {
for (const auto& [cmd, argspec] : cmds->second) {
if (IsArgSet(cmd)) {
found.push_back(cmd);
}
}
if (found.size() > 1) {
throw std::runtime_error(strprintf("Only one of %s may be specified.", util::Join(found, ", ")));
}
}
}

std::string ArgsManager::GetHelpMessage() const
{
const bool show_debug = GetBoolArg("-help-debug", false);
Expand Down Expand Up @@ -635,6 +653,9 @@ std::string ArgsManager::GetHelpMessage() const
case OptionsCategory::REGISTER_COMMANDS:
usage += HelpMessageGroup("Register Commands:");
break;
case OptionsCategory::CLI_COMMANDS:
usage += HelpMessageGroup("CLI Commands:");
break;
default:
break;
}
Expand Down
8 changes: 8 additions & 0 deletions src/common/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enum class OptionsCategory {
GUI,
COMMANDS,
REGISTER_COMMANDS,
CLI_COMMANDS,

HIDDEN // Always the last option to avoid printing these in the help
};
Expand Down Expand Up @@ -363,6 +364,13 @@ class ArgsManager
m_network_only_args.clear();
}

/**
* Check CLI command args
*
* @throws std::runtime_error when multiple CLI_COMMAND arguments are specified
*/
void CheckMultipleCLIArgs() const;

/**
* Get the help string
*/
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ FUZZ_TARGET(system, .init = initialize_system)
args_manager.SoftSetBoolArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeBool());
},
[&] {
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});
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});
// Avoid hitting:
// common/args.cpp:563: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));
Expand Down
3 changes: 3 additions & 0 deletions test/functional/interface_bitcoin_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ def run_test(self):
assert_raises_process_error(1, "Could not connect to the server", self.nodes[0].cli('-rpcwait', '-rpcwaittimeout=5').echo)
assert_greater_than_or_equal(time.time(), start_time + 5)

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


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

0 comments on commit 8127654

Please sign in to comment.