system.cpp raw
1 // Copyright (c) 2020-present The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include <common/args.h>
6 #include <test/fuzz/FuzzedDataProvider.h>
7 #include <test/fuzz/fuzz.h>
8 #include <test/fuzz/util.h>
9 #include <test/util/setup_common.h>
10
11 #include <cstdint>
12 #include <set>
13 #include <string>
14 #include <vector>
15
16 namespace {
17 void initialize_system()
18 {
19 static const auto testing_setup = MakeNoLogFileContext<>();
20 }
21
22 std::string GetArgumentName(const std::string& name)
23 {
24 size_t idx = name.find('=');
25 if (idx == std::string::npos) {
26 idx = name.size();
27 }
28 return name.substr(0, idx);
29 }
30
31 FUZZ_TARGET(system, .init = initialize_system)
32 {
33 FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
34 ArgsManager args_manager{};
35 std::vector<std::string> command_option_names;
36
37 if (fuzzed_data_provider.ConsumeBool()) {
38 SetupHelpOptions(args_manager);
39 }
40
41 LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 3000)
42 {
43 CallOneOf(
44 fuzzed_data_provider,
45 [&] {
46 args_manager.SelectConfigNetwork(fuzzed_data_provider.ConsumeRandomLengthString(16));
47 },
48 [&] {
49 auto str_arg = fuzzed_data_provider.ConsumeRandomLengthString(16);
50 auto str_value = fuzzed_data_provider.ConsumeRandomLengthString(16);
51 args_manager.SoftSetArg(str_arg, str_value);
52 },
53 [&] {
54 auto str_arg = fuzzed_data_provider.ConsumeRandomLengthString(16);
55 auto str_value = fuzzed_data_provider.ConsumeRandomLengthString(16);
56 args_manager.ForceSetArg(str_arg, str_value);
57 },
58 [&] {
59 auto str_arg = fuzzed_data_provider.ConsumeRandomLengthString(16);
60 auto f_value = fuzzed_data_provider.ConsumeBool();
61 args_manager.SoftSetBoolArg(str_arg, f_value);
62 },
63 [&] {
64 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::IPC, OptionsCategory::COMMAND_OPTIONS, OptionsCategory::HIDDEN});
65 // Avoid hitting:
66 // common/args.cpp:563: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
67 const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));
68 if (args_manager.GetArgFlags(argument_name) != std::nullopt) {
69 return;
70 }
71 auto help = fuzzed_data_provider.ConsumeRandomLengthString(16);
72 auto flags = fuzzed_data_provider.ConsumeIntegral<unsigned int>() & ~ArgsManager::COMMAND;
73 args_manager.AddArg(argument_name, help, flags, options_category);
74 if (options_category == OptionsCategory::COMMAND_OPTIONS) {
75 command_option_names.push_back(argument_name);
76 }
77 },
78 [&] {
79 auto cmd = fuzzed_data_provider.ConsumeRandomLengthString(16);
80 if (cmd.empty() || cmd[0] == '-' || cmd.find('=') != std::string::npos) return;
81 if (args_manager.GetArgFlags(cmd) != std::nullopt) return;
82 auto help = fuzzed_data_provider.ConsumeRandomLengthString(16);
83 std::set<std::string> options;
84 for (const auto& opt : command_option_names) {
85 if (fuzzed_data_provider.ConsumeBool()) {
86 options.insert(opt);
87 }
88 }
89 args_manager.AddCommand(cmd, help, std::move(options));
90 },
91 [&] {
92 // Avoid hitting:
93 // common/args.cpp:563: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
94 const std::vector<std::string> names = ConsumeRandomLengthStringVector(fuzzed_data_provider);
95 std::vector<std::string> hidden_arguments;
96 for (const std::string& name : names) {
97 const std::string hidden_argument = GetArgumentName(name);
98 if (args_manager.GetArgFlags(hidden_argument) != std::nullopt) {
99 continue;
100 }
101 if (std::find(hidden_arguments.begin(), hidden_arguments.end(), hidden_argument) != hidden_arguments.end()) {
102 continue;
103 }
104 hidden_arguments.push_back(hidden_argument);
105 }
106 args_manager.AddHiddenArgs(hidden_arguments);
107 },
108 [&] {
109 args_manager.ClearArgs();
110 command_option_names.clear();
111 },
112 [&] {
113 const std::vector<std::string> random_arguments = ConsumeRandomLengthStringVector(fuzzed_data_provider);
114 std::vector<const char*> argv;
115 argv.reserve(random_arguments.size());
116 for (const std::string& random_argument : random_arguments) {
117 argv.push_back(random_argument.c_str());
118 }
119 try {
120 std::string error;
121 (void)args_manager.ParseParameters(argv.size(), argv.data(), error);
122 } catch (const std::logic_error&) {
123 }
124 });
125 }
126
127 const std::string s1 = fuzzed_data_provider.ConsumeRandomLengthString(16);
128 const std::string s2 = fuzzed_data_provider.ConsumeRandomLengthString(16);
129 const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
130 const bool b = fuzzed_data_provider.ConsumeBool();
131
132 (void)args_manager.GetIntArg(s1, i64);
133 (void)args_manager.GetArg(s1, s2);
134 (void)args_manager.GetArgFlags(s1);
135 (void)args_manager.GetArgs(s1);
136 (void)args_manager.GetBoolArg(s1, b);
137 try {
138 (void)args_manager.GetChainTypeString();
139 } catch (const std::runtime_error&) {
140 }
141 (void)args_manager.GetHelpMessage();
142 const auto command = args_manager.GetCommand();
143 if (command) {
144 (void)args_manager.CheckCommandOptions(command->command);
145 }
146 (void)args_manager.GetUnrecognizedSections();
147 (void)args_manager.GetUnsuitableSectionOnlyArgs();
148 (void)args_manager.IsArgNegated(s1);
149 (void)args_manager.IsArgSet(s1);
150
151 (void)HelpRequested(args_manager);
152 }
153 } // namespace
154