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