/ src / test / fuzz / connman.cpp
connman.cpp
  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 <addrman.h>
  6  #include <chainparams.h>
  7  #include <common/args.h>
  8  #include <net.h>
  9  #include <net_processing.h>
 10  #include <netaddress.h>
 11  #include <protocol.h>
 12  #include <test/fuzz/FuzzedDataProvider.h>
 13  #include <test/fuzz/fuzz.h>
 14  #include <test/fuzz/util.h>
 15  #include <test/fuzz/util/net.h>
 16  #include <test/fuzz/util/threadinterrupt.h>
 17  #include <test/util/setup_common.h>
 18  #include <util/translation.h>
 19  
 20  #include <cstdint>
 21  #include <vector>
 22  
 23  namespace {
 24  const TestingSetup* g_setup;
 25  
 26  int32_t GetCheckRatio()
 27  {
 28      return std::clamp<int32_t>(g_setup->m_node.args->GetIntArg("-checkaddrman", 0), 0, 1000000);
 29  }
 30  
 31  } // namespace
 32  
 33  void initialize_connman()
 34  {
 35      static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
 36      g_setup = testing_setup.get();
 37  }
 38  
 39  FUZZ_TARGET(connman, .init = initialize_connman)
 40  {
 41      SeedRandomStateForTest(SeedRand::ZEROS);
 42      FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
 43      SetMockTime(ConsumeTime(fuzzed_data_provider));
 44      auto netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
 45      auto addr_man_ptr{std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio())};
 46      if (fuzzed_data_provider.ConsumeBool()) {
 47          const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
 48          DataStream ds{serialized_data};
 49          try {
 50              ds >> *addr_man_ptr;
 51          } catch (const std::ios_base::failure&) {
 52              addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
 53          }
 54      }
 55      AddrManDeterministic& addr_man{*addr_man_ptr};
 56      auto net_events{ConsumeNetEvents(fuzzed_data_provider)};
 57  
 58      // Mock CreateSock() to create FuzzedSock.
 59      auto CreateSockOrig = CreateSock;
 60      CreateSock = [&fuzzed_data_provider](int, int, int) {
 61          return std::make_unique<FuzzedSock>(fuzzed_data_provider);
 62      };
 63  
 64      // Mock g_dns_lookup() to return a fuzzed address.
 65      auto g_dns_lookup_orig = g_dns_lookup;
 66      g_dns_lookup = [&fuzzed_data_provider](const std::string&, bool) {
 67          return std::vector<CNetAddr>{ConsumeNetAddr(fuzzed_data_provider)};
 68      };
 69  
 70      ConnmanTestMsg connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
 71                       fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
 72                       addr_man,
 73                       netgroupman,
 74                       Params(),
 75                       fuzzed_data_provider.ConsumeBool(),
 76                       ConsumeThreadInterrupt(fuzzed_data_provider)};
 77  
 78      const uint64_t max_outbound_limit{fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
 79      CConnman::Options options;
 80      options.m_msgproc = &net_events;
 81      options.nMaxOutboundLimit = max_outbound_limit;
 82      connman.Init(options);
 83  
 84      CNetAddr random_netaddr;
 85      CAddress random_address;
 86      CNode random_node = ConsumeNode(fuzzed_data_provider);
 87      CSubNet random_subnet;
 88      std::string random_string;
 89  
 90      LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
 91          CNode& p2p_node{*ConsumeNodeAsUniquePtr(fuzzed_data_provider).release()};
 92          connman.AddTestNode(p2p_node);
 93      }
 94  
 95      LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
 96          CallOneOf(
 97              fuzzed_data_provider,
 98              [&] {
 99                  random_netaddr = ConsumeNetAddr(fuzzed_data_provider);
100              },
101              [&] {
102                  random_address = ConsumeAddress(fuzzed_data_provider);
103              },
104              [&] {
105                  random_subnet = ConsumeSubNet(fuzzed_data_provider);
106              },
107              [&] {
108                  random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
109              },
110              [&] {
111                  connman.AddNode({random_string, fuzzed_data_provider.ConsumeBool()});
112              },
113              [&] {
114                  connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
115              },
116              [&] {
117                  connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>());
118              },
119              [&] {
120                  connman.DisconnectNode(random_netaddr);
121              },
122              [&] {
123                  connman.DisconnectNode(random_string);
124              },
125              [&] {
126                  connman.DisconnectNode(random_subnet);
127              },
128              [&] {
129                  connman.ForEachNode([](auto) {});
130              },
131              [&] {
132                  (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); });
133              },
134              [&] {
135                  auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();
136                  auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
137                  auto filtered = fuzzed_data_provider.ConsumeBool();
138                  (void)connman.GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt, filtered);
139              },
140              [&] {
141                  auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();
142                  auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
143                  (void)connman.GetAddresses(/*requestor=*/random_node, max_addresses, max_pct);
144              },
145              [&] {
146                  (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
147              },
148              [&] {
149                  (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both}));
150              },
151              [&] {
152                  (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());
153              },
154              [&] {
155                  CSerializedNetMsg serialized_net_msg;
156                  serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::MESSAGE_TYPE_SIZE);
157                  serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
158                  connman.PushMessage(&random_node, std::move(serialized_net_msg));
159              },
160              [&] {
161                  connman.RemoveAddedNode(random_string);
162              },
163              [&] {
164                  connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
165              },
166              [&] {
167                  connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
168              },
169              [&] {
170                  ConnectionType conn_type{
171                      fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES)};
172                  if (conn_type == ConnectionType::INBOUND) { // INBOUND is not allowed
173                      conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
174                  }
175  
176                  connman.OpenNetworkConnection(
177                      /*addrConnect=*/random_address,
178                      /*fCountFailure=*/fuzzed_data_provider.ConsumeBool(),
179                      /*grant_outbound=*/{},
180                      /*pszDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(),
181                      /*conn_type=*/conn_type,
182                      /*use_v2transport=*/fuzzed_data_provider.ConsumeBool());
183              },
184              [&] {
185                  connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
186                  const auto peer = ConsumeAddress(fuzzed_data_provider);
187                  connman.CreateNodeFromAcceptedSocketPublic(
188                      /*sock=*/CreateSock(AF_INET, SOCK_STREAM, IPPROTO_TCP),
189                      /*permissions=*/ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS),
190                      /*addr_bind=*/ConsumeAddress(fuzzed_data_provider),
191                      /*addr_peer=*/peer);
192              },
193              [&] {
194                  CConnman::Options options;
195  
196                  options.vBinds = ConsumeServiceVector(fuzzed_data_provider);
197  
198                  options.vWhiteBinds = std::vector<NetWhitebindPermissions>{
199                      fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 5)};
200                  for (auto& wb : options.vWhiteBinds) {
201                      wb.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
202                      wb.m_service = ConsumeService(fuzzed_data_provider);
203                  }
204  
205                  options.onion_binds = ConsumeServiceVector(fuzzed_data_provider);
206  
207                  options.bind_on_any = options.vBinds.empty() && options.vWhiteBinds.empty() &&
208                                        options.onion_binds.empty();
209  
210                  connman.InitBindsPublic(options);
211              },
212              [&] {
213                  connman.SocketHandlerPublic();
214              });
215      }
216      (void)connman.GetAddedNodeInfo(fuzzed_data_provider.ConsumeBool());
217      (void)connman.GetExtraFullOutboundCount();
218      (void)connman.GetLocalServices();
219      assert(connman.GetMaxOutboundTarget() == max_outbound_limit);
220      (void)connman.GetMaxOutboundTimeframe();
221      (void)connman.GetMaxOutboundTimeLeftInCycle();
222      (void)connman.GetNetworkActive();
223      std::vector<CNodeStats> stats;
224      connman.GetNodeStats(stats);
225      (void)connman.GetOutboundTargetBytesLeft();
226      (void)connman.GetTotalBytesRecv();
227      (void)connman.GetTotalBytesSent();
228      (void)connman.GetTryNewOutboundPeer();
229      (void)connman.GetUseAddrmanOutgoing();
230      (void)connman.ASMapHealthCheck();
231  
232      connman.ClearTestNodes();
233      g_dns_lookup = g_dns_lookup_orig;
234      CreateSock = CreateSockOrig;
235  }