1 // Copyright (c) 2020-2021 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 <test/fuzz/FuzzedDataProvider.h>
6 #include <test/fuzz/fuzz.h>
7 #include <test/fuzz/util.h>
8 #include <util/system.h>
9 
10 #include <cstdint>
11 #include <string>
12 #include <vector>
13 
14 namespace {
GetArgumentName(const std::string & name)15 std::string GetArgumentName(const std::string& name)
16 {
17     size_t idx = name.find('=');
18     if (idx == std::string::npos) {
19         idx = name.size();
20     }
21     return name.substr(0, idx);
22 }
23 } // namespace
24 
FUZZ_TARGET(system)25 FUZZ_TARGET(system)
26 {
27     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
28     ArgsManager args_manager{};
29 
30     if (fuzzed_data_provider.ConsumeBool()) {
31         SetupHelpOptions(args_manager);
32     }
33 
34     while (fuzzed_data_provider.ConsumeBool()) {
35         CallOneOf(
36             fuzzed_data_provider,
37             [&] {
38                 args_manager.SelectConfigNetwork(fuzzed_data_provider.ConsumeRandomLengthString(16));
39             },
40             [&] {
41                 args_manager.SoftSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
42             },
43             [&] {
44                 args_manager.ForceSetArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeRandomLengthString(16));
45             },
46             [&] {
47                 args_manager.SoftSetBoolArg(fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeBool());
48             },
49             [&] {
50                 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});
51                 // Avoid hitting:
52                 // util/system.cpp:425: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
53                 const std::string argument_name = GetArgumentName(fuzzed_data_provider.ConsumeRandomLengthString(16));
54                 if (args_manager.GetArgFlags(argument_name) != std::nullopt) {
55                     return;
56                 }
57                 args_manager.AddArg(argument_name, fuzzed_data_provider.ConsumeRandomLengthString(16), fuzzed_data_provider.ConsumeIntegral<unsigned int>() & ~ArgsManager::COMMAND, options_category);
58             },
59             [&] {
60                 // Avoid hitting:
61                 // util/system.cpp:425: void ArgsManager::AddArg(const std::string &, const std::string &, unsigned int, const OptionsCategory &): Assertion `ret.second' failed.
62                 const std::vector<std::string> names = ConsumeRandomLengthStringVector(fuzzed_data_provider);
63                 std::vector<std::string> hidden_arguments;
64                 for (const std::string& name : names) {
65                     const std::string hidden_argument = GetArgumentName(name);
66                     if (args_manager.GetArgFlags(hidden_argument) != std::nullopt) {
67                         continue;
68                     }
69                     if (std::find(hidden_arguments.begin(), hidden_arguments.end(), hidden_argument) != hidden_arguments.end()) {
70                         continue;
71                     }
72                     hidden_arguments.push_back(hidden_argument);
73                 }
74                 args_manager.AddHiddenArgs(hidden_arguments);
75             },
76             [&] {
77                 args_manager.ClearArgs();
78             },
79             [&] {
80                 const std::vector<std::string> random_arguments = ConsumeRandomLengthStringVector(fuzzed_data_provider);
81                 std::vector<const char*> argv;
82                 argv.reserve(random_arguments.size());
83                 for (const std::string& random_argument : random_arguments) {
84                     argv.push_back(random_argument.c_str());
85                 }
86                 try {
87                     std::string error;
88                     (void)args_manager.ParseParameters(argv.size(), argv.data(), error);
89                 } catch (const std::logic_error&) {
90                 }
91             });
92     }
93 
94     const std::string s1 = fuzzed_data_provider.ConsumeRandomLengthString(16);
95     const std::string s2 = fuzzed_data_provider.ConsumeRandomLengthString(16);
96     const int64_t i64 = fuzzed_data_provider.ConsumeIntegral<int64_t>();
97     const bool b = fuzzed_data_provider.ConsumeBool();
98 
99     (void)args_manager.GetArg(s1, i64);
100     (void)args_manager.GetArg(s1, s2);
101     (void)args_manager.GetArgFlags(s1);
102     (void)args_manager.GetArgs(s1);
103     (void)args_manager.GetBoolArg(s1, b);
104     try {
105         (void)args_manager.GetChainName();
106     } catch (const std::runtime_error&) {
107     }
108     (void)args_manager.GetHelpMessage();
109     (void)args_manager.GetUnrecognizedSections();
110     (void)args_manager.GetUnsuitableSectionOnlyArgs();
111     (void)args_manager.IsArgNegated(s1);
112     (void)args_manager.IsArgSet(s1);
113 
114     (void)HelpRequested(args_manager);
115 }
116