Branch data Line data Source code
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 <test/util/time.h>
19 : : #include <util/check.h>
20 : : #include <util/translation.h>
21 : :
22 : : #include <cstdint>
23 : : #include <vector>
24 : :
25 : : namespace {
26 : : const TestingSetup* g_setup;
27 : :
28 : 5779 : int32_t GetCheckRatio()
29 : : {
30 [ + - ]: 17337 : return std::clamp<int32_t>(g_setup->m_node.args->GetIntArg("-checkaddrman", 0), 0, 1000000);
31 : : }
32 : :
33 : : } // namespace
34 : :
35 : 1 : void initialize_connman()
36 : : {
37 [ + - + - : 1 : static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();
+ - ]
38 : 1 : g_setup = testing_setup.get();
39 : 1 : }
40 : :
41 [ + - ]: 4917 : FUZZ_TARGET(connman, .init = initialize_connman)
42 : : {
43 : 4441 : SeedRandomStateForTest(SeedRand::ZEROS);
44 : 4441 : FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
45 : 4441 : FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)};
46 [ + - ]: 4441 : FakeSteadyClock steady_clock;
47 : 4441 : auto netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
48 [ + - + - ]: 4441 : auto addr_man_ptr{std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio())};
49 [ + + ]: 4441 : if (fuzzed_data_provider.ConsumeBool()) {
50 : 2111 : const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
51 [ - + + - ]: 2111 : DataStream ds{serialized_data};
52 : 2111 : try {
53 [ + + ]: 4222 : ds >> *addr_man_ptr;
54 [ - + ]: 1338 : } catch (const std::ios_base::failure&) {
55 [ + - + - ]: 2676 : addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
56 : 1338 : }
57 : 2111 : }
58 [ + - ]: 4441 : AddrManDeterministic& addr_man{*addr_man_ptr};
59 [ + - ]: 4441 : auto net_events{ConsumeNetEvents(fuzzed_data_provider)};
60 : :
61 : : // Mock CreateSock() to create FuzzedSock.
62 [ + - ]: 4441 : auto CreateSockOrig = CreateSock;
63 : 4441 : CreateSock = [&fuzzed_data_provider, &steady_clock](int, int, int) {
64 : 108577 : return std::make_unique<FuzzedSock>(fuzzed_data_provider, steady_clock);
65 : 4441 : };
66 : :
67 : : // Mock g_dns_lookup() to return a fuzzed address.
68 [ + - ]: 4441 : auto g_dns_lookup_orig = g_dns_lookup;
69 : 50012 : g_dns_lookup = [&fuzzed_data_provider](const std::string&, bool) {
70 [ + - + + : 136713 : return std::vector<CNetAddr>{ConsumeNetAddr(fuzzed_data_provider)};
- - ]
71 : 50012 : };
72 : :
73 : 4441 : ConnmanTestMsg connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
74 : : fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
75 : : addr_man,
76 : : netgroupman,
77 : : Params(),
78 : 4441 : fuzzed_data_provider.ConsumeBool(),
79 [ + - + - : 8882 : ConsumeThreadInterrupt(fuzzed_data_provider)};
+ - ]
80 : :
81 : 4441 : const uint64_t max_outbound_limit{fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
82 : 4441 : CConnman::Options options;
83 : 4441 : options.m_msgproc = &net_events;
84 : 4441 : options.nMaxOutboundLimit = max_outbound_limit;
85 : :
86 : 4441 : const auto local_services{ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS)};
87 : 4441 : options.m_local_services = local_services;
88 : :
89 : 4441 : const auto use_addrman_outgoing{fuzzed_data_provider.ConsumeBool()};
90 : 4441 : options.m_use_addrman_outgoing = use_addrman_outgoing;
91 : 4441 : options.m_max_automatic_connections = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1000);
92 : :
93 : 13323 : auto consume_whitelist = [&]() {
94 : 8882 : std::vector<NetWhitelistPermissions> result(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3));
95 [ + + ]: 15925 : for (auto& entry : result) {
96 : 7043 : entry.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
97 : 7043 : entry.m_subnet = ConsumeSubNet(fuzzed_data_provider);
98 : : }
99 : 8882 : return result;
100 : 4441 : };
101 [ + - ]: 8882 : options.vWhitelistedRangeIncoming = consume_whitelist();
102 [ + - ]: 8882 : options.vWhitelistedRangeOutgoing = consume_whitelist();
103 : :
104 [ + - ]: 4441 : connman.Init(options);
105 : :
106 [ + - ]: 4441 : const uint64_t total_bytes_recv_initial{connman.GetTotalBytesRecv()};
107 [ + - ]: 4441 : const uint64_t total_bytes_sent_initial{connman.GetTotalBytesSent()};
108 : :
109 [ + - ]: 4441 : CNetAddr random_netaddr;
110 [ + - ]: 4441 : CAddress random_address;
111 : 4441 : CNode random_node = ConsumeNode(fuzzed_data_provider, steady_clock);
112 [ + - ]: 4441 : CSubNet random_subnet;
113 : 4441 : std::string random_string;
114 : 4441 : std::vector<NodeId> node_ids;
115 : 4441 : std::vector<std::string> node_addr_names;
116 : :
117 [ + + + + ]: 70769 : LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 100) {
118 : 66328 : CNode& p2p_node{*ConsumeNodeAsUniquePtr(fuzzed_data_provider, steady_clock).release()};
119 : : // Simulate post-handshake state.
120 [ + - ]: 66328 : p2p_node.fSuccessfullyConnected = true;
121 [ + - ]: 66328 : connman.AddTestNode(p2p_node);
122 [ + - ]: 66328 : node_ids.push_back(p2p_node.GetId());
123 [ + - ]: 66328 : node_addr_names.push_back(p2p_node.m_addr_name);
124 : : }
125 : :
126 [ + + + + ]: 1178936 : LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 10000) {
127 [ + - ]: 1174495 : CallOneOf(
128 : : fuzzed_data_provider,
129 : 23861 : [&] {
130 : 23861 : random_netaddr = ConsumeNetAddr(fuzzed_data_provider);
131 : 23861 : },
132 : 45739 : [&] {
133 : 45739 : random_address = ConsumeAddress(fuzzed_data_provider);
134 : 45739 : },
135 : 10397 : [&] {
136 : 10397 : random_subnet = ConsumeSubNet(fuzzed_data_provider);
137 : 10397 : },
138 : 40326 : [&] {
139 : 40326 : random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
140 : 40326 : },
141 : 30718 : [&] {
142 [ + + ]: 22663 : const std::string& node_str = (!node_addr_names.empty() && fuzzed_data_provider.ConsumeBool())
143 [ + + ]: 52985 : ? PickValue(fuzzed_data_provider, node_addr_names)
144 : 30718 : : random_string;
145 : 30718 : const auto added_node_info{connman.GetAddedNodeInfo(/*include_connected=*/true)};
146 [ - + ]: 61436 : const auto add_node{connman.AddNode({node_str, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()})};
147 [ + + ]: 30718 : if (add_node) {
148 [ - + - + ]: 43108 : assert(!connman.AddNode({node_str, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()}));
149 [ - + + - : 43108 : assert(added_node_info.size() < connman.GetAddedNodeInfo(/*include_connected=*/true).size());
- + ]
150 : 21554 : const auto remove{fuzzed_data_provider.ConsumeBool()};
151 [ + + ]: 21554 : if (remove) {
152 [ - + + - : 20611 : assert(connman.RemoveAddedNode(node_str));
- + ]
153 [ - + + - : 41222 : assert(added_node_info.size() == connman.GetAddedNodeInfo(/*include_connected=*/true).size());
- + ]
154 : : }
155 : : }
156 [ + - + - ]: 82990 : },
157 : 73361 : [&] {
158 [ - + ]: 73361 : (void)connman.RemoveAddedNode(random_string);
159 : 73361 : },
160 : 5133 : [&] {
161 : 5133 : connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
162 : 5133 : },
163 : 4640 : [&] {
164 : 4640 : connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>());
165 : 4640 : },
166 : 7977 : [&] {
167 : 7977 : connman.DisconnectNode(random_netaddr);
168 : 7977 : },
169 : 8718 : [&] {
170 [ - + ]: 8718 : connman.DisconnectNode(random_string);
171 : 8718 : },
172 : 51772 : [&] {
173 : 51772 : connman.DisconnectNode(random_subnet);
174 : 51772 : },
175 : 2439 : [&] {
176 [ + + ]: 1188 : NodeId id = node_ids.empty() || fuzzed_data_provider.ConsumeBool()
177 [ + + ]: 3295 : ? fuzzed_data_provider.ConsumeIntegral<NodeId>()
178 : 2439 : : PickValue(fuzzed_data_provider, node_ids);
179 [ + - ]: 2439 : (void)connman.ForNode(id, [&](CNode* pnode) {
180 : : (void)pnode->GetId();
181 : : (void)pnode->IsInboundConn();
182 : : (void)pnode->IsFullOutboundConn();
183 : : return true;
184 : : });
185 : 2439 : },
186 : 32616 : [&] {
187 : 32616 : auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();
188 : 32616 : auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
189 : 32616 : auto filtered = fuzzed_data_provider.ConsumeBool();
190 : 32616 : (void)connman.GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt, filtered);
191 : 32616 : },
192 : 2808 : [&] {
193 : 2808 : auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();
194 : 2808 : auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
195 : 2808 : (void)connman.GetAddresses(/*requestor=*/random_node, max_addresses, max_pct);
196 : 2808 : },
197 : 1172 : [&] {
198 : 1172 : (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
199 : 1172 : },
200 : 13070 : [&] {
201 : 13070 : (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both}));
202 : 13070 : },
203 : 338061 : [&] {
204 : 338061 : (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());
205 : 338061 : },
206 : 93980 : [&] {
207 [ + - ]: 93980 : CSerializedNetMsg serialized_net_msg;
208 [ + - ]: 93980 : serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::MESSAGE_TYPE_SIZE);
209 : 93980 : serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
210 [ + - ]: 93980 : const auto nodes{connman.TestNodes()};
211 [ + + ]: 93980 : if (nodes.empty()) return;
212 : 84051 : CNode* receiver{PickValue(fuzzed_data_provider, nodes)};
213 [ + - ]: 84051 : connman.PushMessage(receiver, std::move(serialized_net_msg));
214 : 187960 : },
215 : 7840 : [&] {
216 : 7840 : const auto set_active{fuzzed_data_provider.ConsumeBool()};
217 : 7840 : connman.SetNetworkActive(set_active);
218 [ - + ]: 7840 : assert(connman.GetNetworkActive() == set_active);
219 : 7840 : },
220 : 231572 : [&] {
221 : 231572 : connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
222 : 231572 : },
223 : 1891 : [&] {
224 : 1891 : const auto services{ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS)};
225 : 1891 : const auto before{connman.GetLocalServices()};
226 [ + + ]: 1891 : if (fuzzed_data_provider.ConsumeBool()) {
227 : 761 : connman.AddLocalServices(services);
228 [ - + ]: 761 : assert((connman.GetLocalServices() & services) == services);
229 : : // Restore by clearing only the bits that weren't already set.
230 : 761 : connman.RemoveLocalServices(ServiceFlags(services & ~before));
231 : : } else {
232 : 1130 : connman.RemoveLocalServices(services);
233 [ - + ]: 1130 : assert((connman.GetLocalServices() & services) == 0);
234 : : // Restore by re-adding only the bits that were previously set.
235 : 1130 : connman.AddLocalServices(ServiceFlags(services & before));
236 : : }
237 [ - + ]: 1891 : assert(connman.GetLocalServices() == before);
238 : 1891 : },
239 : 28190 : [&] {
240 : 28190 : ConnectionType conn_type{
241 : 28190 : fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES)};
242 [ + + ]: 28190 : if (conn_type == ConnectionType::INBOUND) { // INBOUND is not allowed
243 : 2797 : conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
244 : : }
245 : :
246 : 28190 : std::optional<Proxy> proxy_override;
247 [ + + + + ]: 28190 : if (conn_type == ConnectionType::PRIVATE_BROADCAST || fuzzed_data_provider.ConsumeBool()) {
248 : 22514 : proxy_override.emplace(ConsumeService(fuzzed_data_provider));
249 : : }
250 : :
251 [ + + ]: 28190 : connman.OpenNetworkConnection(
252 : : /*addrConnect=*/random_address,
253 [ + - ]: 28190 : /*fCountFailure=*/fuzzed_data_provider.ConsumeBool(),
254 : : /*grant_outbound=*/{},
255 [ + + ]: 28190 : /*pszDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(),
256 : : /*conn_type=*/conn_type,
257 : 28190 : /*use_v2transport=*/fuzzed_data_provider.ConsumeBool(),
258 : : /*proxy_override=*/proxy_override);
259 : 28190 : },
260 : 64728 : [&] {
261 : 64728 : connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
262 : 64728 : const auto peer = ConsumeAddress(fuzzed_data_provider);
263 : 64728 : connman.CreateNodeFromAcceptedSocketPublic(
264 [ + - ]: 129456 : /*sock=*/CreateSock(AF_INET, SOCK_STREAM, IPPROTO_TCP),
265 : : /*permissions=*/ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS),
266 : 129456 : /*addr_bind=*/ConsumeAddress(fuzzed_data_provider),
267 : : /*addr_peer=*/peer);
268 : 64728 : },
269 : 26147 : [&] {
270 : 26147 : CConnman::Options options;
271 : :
272 : 26147 : options.vBinds = ConsumeServiceVector(fuzzed_data_provider);
273 : :
274 : 26147 : options.vWhiteBinds = std::vector<NetWhitebindPermissions>{
275 [ + - ]: 52294 : fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 5)};
276 [ + + ]: 56048 : for (auto& wb : options.vWhiteBinds) {
277 : 29901 : wb.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
278 : 29901 : wb.m_service = ConsumeService(fuzzed_data_provider);
279 : : }
280 : :
281 : 26147 : options.onion_binds = ConsumeServiceVector(fuzzed_data_provider);
282 : :
283 [ + + + + ]: 26147 : options.bind_on_any = options.vBinds.empty() && options.vWhiteBinds.empty() &&
284 [ + + ]: 7571 : options.onion_binds.empty();
285 : :
286 [ + - ]: 26147 : connman.InitBindsPublic(options);
287 : 26147 : },
288 : 27339 : [&] {
289 : 27339 : connman.SocketHandlerPublic();
290 : 27339 : });
291 : : }
292 [ + - ]: 65098 : connman.ForEachNode([](CNode* pnode) {
293 : 60657 : (void)pnode->GetId();
294 : 60657 : (void)pnode->IsInboundConn();
295 : 60657 : (void)pnode->IsFullOutboundConn();
296 : 60657 : (void)pnode->ConnectionTypeAsString();
297 : 60657 : });
298 [ + - ]: 4441 : (void)connman.GetAddedNodeInfo(/*include_connected=*/false);
299 [ + - ]: 4441 : (void)connman.GetExtraFullOutboundCount();
300 [ + - - + ]: 4441 : assert(connman.GetLocalServices() == local_services);
301 [ + - - + ]: 4441 : assert(connman.GetMaxOutboundTarget() == max_outbound_limit);
302 [ + - ]: 4441 : const auto time_left_in_cycle{connman.GetMaxOutboundTimeLeftInCycle()};
303 : 4441 : std::vector<CNodeStats> stats;
304 [ + - ]: 4441 : connman.GetNodeStats(stats);
305 [ + - ]: 4441 : const auto bytes_left{connman.GetOutboundTargetBytesLeft()};
306 [ - + ]: 4441 : assert(bytes_left <= max_outbound_limit);
307 [ + + ]: 4441 : if (max_outbound_limit == 0) {
308 [ - + ]: 1067 : assert(bytes_left == 0);
309 [ - + ]: 1067 : assert(time_left_in_cycle == std::chrono::seconds{0});
310 [ + - - + ]: 1067 : assert(!connman.OutboundTargetReached(/*historicalBlockServingLimit=*/false));
311 [ + - - + ]: 1067 : assert(!connman.OutboundTargetReached(/*historicalBlockServingLimit=*/true));
312 : : }
313 [ + - - + ]: 4441 : assert(connman.GetTotalBytesRecv() >= total_bytes_recv_initial);
314 [ + - - + ]: 4441 : assert(connman.GetTotalBytesSent() >= total_bytes_sent_initial);
315 [ + - ]: 4441 : (void)connman.GetTryNewOutboundPeer();
316 [ - + ]: 4441 : assert(connman.GetUseAddrmanOutgoing() == use_addrman_outgoing);
317 [ + - ]: 4441 : (void)connman.ASMapHealthCheck();
318 : :
319 [ + - ]: 4441 : connman.ClearTestNodes();
320 [ + - ]: 4441 : g_dns_lookup = g_dns_lookup_orig;
321 [ + - ]: 4441 : CreateSock = CreateSockOrig;
322 : 4441 : }
|