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 : 4549 : int32_t GetCheckRatio()
28 : : {
29 [ + - ]: 13647 : 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 [ + - ]: 3851 : FUZZ_TARGET(connman, .init = initialize_connman)
41 : : {
42 : 3391 : SeedRandomStateForTest(SeedRand::ZEROS);
43 : 3391 : FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
44 : 3391 : NodeClockContext clock_ctx{ConsumeTime(fuzzed_data_provider)};
45 : 3391 : auto netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
46 [ + - + - ]: 3391 : auto addr_man_ptr{std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio())};
47 [ + + ]: 3391 : if (fuzzed_data_provider.ConsumeBool()) {
48 : 1801 : const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
49 [ - + + - ]: 1801 : DataStream ds{serialized_data};
50 : 1801 : try {
51 [ + + ]: 3602 : ds >> *addr_man_ptr;
52 [ - + ]: 1158 : } catch (const std::ios_base::failure&) {
53 [ + - + - ]: 2316 : addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
54 : 1158 : }
55 : 1801 : }
56 [ + - ]: 3391 : AddrManDeterministic& addr_man{*addr_man_ptr};
57 [ + - ]: 3391 : auto net_events{ConsumeNetEvents(fuzzed_data_provider)};
58 : :
59 : : // Mock CreateSock() to create FuzzedSock.
60 [ + - ]: 3391 : auto CreateSockOrig = CreateSock;
61 : 3901 : CreateSock = [&fuzzed_data_provider](int, int, int) {
62 : 510 : return std::make_unique<FuzzedSock>(fuzzed_data_provider);
63 : 3391 : };
64 : :
65 : : // Mock g_dns_lookup() to return a fuzzed address.
66 [ + - ]: 3391 : auto g_dns_lookup_orig = g_dns_lookup;
67 : 3402 : g_dns_lookup = [&fuzzed_data_provider](const std::string&, bool) {
68 [ + - + + : 33 : return std::vector<CNetAddr>{ConsumeNetAddr(fuzzed_data_provider)};
- - ]
69 : 3402 : };
70 : :
71 : 3391 : ConnmanTestMsg connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
72 : : fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
73 : : addr_man,
74 : : netgroupman,
75 : : Params(),
76 : 3391 : fuzzed_data_provider.ConsumeBool(),
77 [ + - + - : 6782 : ConsumeThreadInterrupt(fuzzed_data_provider)};
+ - ]
78 : :
79 : 3391 : const uint64_t max_outbound_limit{fuzzed_data_provider.ConsumeIntegral<uint64_t>()};
80 : 3391 : CConnman::Options options;
81 : 3391 : options.m_msgproc = &net_events;
82 : 3391 : options.nMaxOutboundLimit = max_outbound_limit;
83 : :
84 : 10173 : auto consume_whitelist = [&]() {
85 : 6782 : std::vector<NetWhitelistPermissions> result(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3));
86 [ + + ]: 13652 : for (auto& entry : result) {
87 : 6870 : entry.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
88 : 6870 : entry.m_subnet = ConsumeSubNet(fuzzed_data_provider);
89 : : }
90 : 6782 : return result;
91 : 3391 : };
92 [ + - ]: 6782 : options.vWhitelistedRangeIncoming = consume_whitelist();
93 [ + - ]: 6782 : options.vWhitelistedRangeOutgoing = consume_whitelist();
94 : :
95 [ + - ]: 3391 : connman.Init(options);
96 : :
97 [ + - ]: 3391 : CNetAddr random_netaddr;
98 [ + - ]: 3391 : CAddress random_address;
99 : 3391 : CNode random_node = ConsumeNode(fuzzed_data_provider);
100 [ + - ]: 3391 : CSubNet random_subnet;
101 : 3391 : std::string random_string;
102 : 3391 : std::vector<NodeId> node_ids;
103 : :
104 [ + + + + ]: 48349 : LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) {
105 : 44958 : CNode& p2p_node{*ConsumeNodeAsUniquePtr(fuzzed_data_provider).release()};
106 : : // Simulate post-handshake state.
107 [ + - ]: 44958 : p2p_node.fSuccessfullyConnected = true;
108 [ + - ]: 44958 : connman.AddTestNode(p2p_node);
109 [ + - ]: 44958 : node_ids.push_back(p2p_node.GetId());
110 : : }
111 : :
112 [ + + + + ]: 441626 : LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
113 [ + - ]: 438235 : CallOneOf(
114 : : fuzzed_data_provider,
115 : 1653 : [&] {
116 : 1653 : random_netaddr = ConsumeNetAddr(fuzzed_data_provider);
117 : 1653 : },
118 : 49235 : [&] {
119 : 49235 : random_address = ConsumeAddress(fuzzed_data_provider);
120 : 49235 : },
121 : 166 : [&] {
122 : 166 : random_subnet = ConsumeSubNet(fuzzed_data_provider);
123 : 166 : },
124 : 62809 : [&] {
125 : 62809 : random_string = fuzzed_data_provider.ConsumeRandomLengthString(64);
126 : 62809 : },
127 : 84 : [&] {
128 : 336 : connman.AddNode({random_string, fuzzed_data_provider.ConsumeBool()});
129 [ - + + - ]: 252 : },
130 : 2453 : [&] {
131 : 2453 : connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
132 : 2453 : },
133 : 131 : [&] {
134 : 131 : connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>());
135 : 131 : },
136 : 96026 : [&] {
137 : 96026 : connman.DisconnectNode(random_netaddr);
138 : 96026 : },
139 : 58 : [&] {
140 [ - + ]: 58 : connman.DisconnectNode(random_string);
141 : 58 : },
142 : 2866 : [&] {
143 : 2866 : connman.DisconnectNode(random_subnet);
144 : 2866 : },
145 : 46 : [&] {
146 [ + + ]: 41 : NodeId id = node_ids.empty() || fuzzed_data_provider.ConsumeBool()
147 [ + + ]: 83 : ? fuzzed_data_provider.ConsumeIntegral<NodeId>()
148 : 46 : : PickValue(fuzzed_data_provider, node_ids);
149 [ + - ]: 46 : (void)connman.ForNode(id, [&](CNode* pnode) {
150 : : (void)pnode->GetId();
151 : : (void)pnode->IsInboundConn();
152 : : (void)pnode->IsFullOutboundConn();
153 : : return true;
154 : : });
155 : 46 : },
156 : 2830 : [&] {
157 : 2830 : auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();
158 : 2830 : auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
159 : 2830 : auto filtered = fuzzed_data_provider.ConsumeBool();
160 : 2830 : (void)connman.GetAddressesUnsafe(max_addresses, max_pct, /*network=*/std::nullopt, filtered);
161 : 2830 : },
162 : 94 : [&] {
163 : 94 : auto max_addresses = fuzzed_data_provider.ConsumeIntegral<size_t>();
164 : 94 : auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
165 : 94 : (void)connman.GetAddresses(/*requestor=*/random_node, max_addresses, max_pct);
166 : 94 : },
167 : 2598 : [&] {
168 : 2598 : (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
169 : 2598 : },
170 : 159 : [&] {
171 : 159 : (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({ConnectionDirection::None, ConnectionDirection::In, ConnectionDirection::Out, ConnectionDirection::Both}));
172 : 159 : },
173 : 15339 : [&] {
174 : 15339 : (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool());
175 : 15339 : },
176 : 38 : [&] {
177 [ + - ]: 38 : CSerializedNetMsg serialized_net_msg;
178 [ + - ]: 38 : serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::MESSAGE_TYPE_SIZE);
179 : 38 : serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider);
180 [ + - ]: 38 : connman.PushMessage(&random_node, std::move(serialized_net_msg));
181 : 38 : },
182 : 34857 : [&] {
183 [ - + ]: 34857 : connman.RemoveAddedNode(random_string);
184 : 34857 : },
185 : 96 : [&] {
186 : 96 : connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
187 : 96 : },
188 : 164523 : [&] {
189 : 164523 : connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool());
190 : 164523 : },
191 : 146 : [&] {
192 : 146 : ConnectionType conn_type{
193 : 146 : fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES)};
194 [ + + ]: 146 : if (conn_type == ConnectionType::INBOUND) { // INBOUND is not allowed
195 : 20 : conn_type = ConnectionType::OUTBOUND_FULL_RELAY;
196 : : }
197 : :
198 [ - + ]: 292 : connman.OpenNetworkConnection(
199 : : /*addrConnect=*/random_address,
200 [ + - ]: 146 : /*fCountFailure=*/fuzzed_data_provider.ConsumeBool(),
201 : : /*grant_outbound=*/{},
202 [ + + ]: 146 : /*pszDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(),
203 : : /*conn_type=*/conn_type,
204 : 146 : /*use_v2transport=*/fuzzed_data_provider.ConsumeBool());
205 : 146 : },
206 : 500 : [&] {
207 : 500 : connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool());
208 : 500 : const auto peer = ConsumeAddress(fuzzed_data_provider);
209 : 500 : connman.CreateNodeFromAcceptedSocketPublic(
210 [ + - ]: 1000 : /*sock=*/CreateSock(AF_INET, SOCK_STREAM, IPPROTO_TCP),
211 : : /*permissions=*/ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS),
212 : 1000 : /*addr_bind=*/ConsumeAddress(fuzzed_data_provider),
213 : : /*addr_peer=*/peer);
214 : 500 : },
215 : 23 : [&] {
216 : 23 : CConnman::Options options;
217 : :
218 : 23 : options.vBinds = ConsumeServiceVector(fuzzed_data_provider);
219 : :
220 : 23 : options.vWhiteBinds = std::vector<NetWhitebindPermissions>{
221 [ + - ]: 46 : fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 5)};
222 [ + + ]: 50 : for (auto& wb : options.vWhiteBinds) {
223 : 27 : wb.m_flags = ConsumeWeakEnum(fuzzed_data_provider, ALL_NET_PERMISSION_FLAGS);
224 : 27 : wb.m_service = ConsumeService(fuzzed_data_provider);
225 : : }
226 : :
227 : 23 : options.onion_binds = ConsumeServiceVector(fuzzed_data_provider);
228 : :
229 [ - + - - ]: 23 : options.bind_on_any = options.vBinds.empty() && options.vWhiteBinds.empty() &&
230 [ # # ]: 0 : options.onion_binds.empty();
231 : :
232 [ + - ]: 23 : connman.InitBindsPublic(options);
233 : 23 : },
234 : 1505 : [&] {
235 : 1505 : connman.SocketHandlerPublic();
236 : 1505 : });
237 : : }
238 [ + - ]: 48007 : connman.ForEachNode([](CNode* pnode) {
239 : 44616 : (void)pnode->GetId();
240 : 44616 : (void)pnode->IsInboundConn();
241 : 44616 : (void)pnode->IsFullOutboundConn();
242 : 44616 : (void)pnode->ConnectionTypeAsString();
243 : 44616 : });
244 [ + - ]: 3391 : (void)connman.GetAddedNodeInfo(fuzzed_data_provider.ConsumeBool());
245 [ + - ]: 3391 : (void)connman.GetExtraFullOutboundCount();
246 [ + - ]: 3391 : (void)connman.GetLocalServices();
247 [ + - - + ]: 3391 : assert(connman.GetMaxOutboundTarget() == max_outbound_limit);
248 [ + - ]: 3391 : (void)connman.GetMaxOutboundTimeframe();
249 [ + - ]: 3391 : (void)connman.GetMaxOutboundTimeLeftInCycle();
250 [ + - ]: 3391 : (void)connman.GetNetworkActive();
251 : 3391 : std::vector<CNodeStats> stats;
252 [ + - ]: 3391 : connman.GetNodeStats(stats);
253 [ + - ]: 3391 : (void)connman.GetOutboundTargetBytesLeft();
254 [ + - ]: 3391 : (void)connman.GetTotalBytesRecv();
255 [ + - ]: 3391 : (void)connman.GetTotalBytesSent();
256 [ + - ]: 3391 : (void)connman.GetTryNewOutboundPeer();
257 : 3391 : (void)connman.GetUseAddrmanOutgoing();
258 [ + - ]: 3391 : (void)connman.ASMapHealthCheck();
259 : :
260 [ + - ]: 3391 : connman.ClearTestNodes();
261 [ + - ]: 3391 : g_dns_lookup = g_dns_lookup_orig;
262 [ + - ]: 3391 : CreateSock = CreateSockOrig;
263 : 3391 : }
|