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