/root/bitcoin/src/test/fuzz/banman.cpp
Line | Count | Source |
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 <banman.h> |
6 | | #include <common/args.h> |
7 | | #include <netaddress.h> |
8 | | #include <test/fuzz/FuzzedDataProvider.h> |
9 | | #include <test/fuzz/fuzz.h> |
10 | | #include <test/fuzz/util.h> |
11 | | #include <test/fuzz/util/net.h> |
12 | | #include <test/util/setup_common.h> |
13 | | #include <test/util/time.h> |
14 | | #include <util/fs.h> |
15 | | #include <util/readwritefile.h> |
16 | | |
17 | | #include <cassert> |
18 | | #include <cstdint> |
19 | | #include <limits> |
20 | | #include <string> |
21 | | #include <vector> |
22 | | |
23 | | namespace { |
24 | | int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept |
25 | 0 | { |
26 | | // Avoid signed integer overflow by capping to int32_t max: |
27 | | // banman.cpp:137:73: runtime error: signed integer overflow: 1591700817 + 9223372036854775807 cannot be represented in type 'long' |
28 | 0 | return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::max()); |
29 | 0 | } |
30 | | } // namespace |
31 | | |
32 | | void initialize_banman() |
33 | 0 | { |
34 | 0 | static const auto testing_setup = MakeNoLogFileContext<>(); |
35 | 0 | } |
36 | | |
37 | | static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs) |
38 | 0 | { |
39 | 0 | return lhs.nVersion == rhs.nVersion && Branch (39:12): [True: 0, False: 0]
|
40 | 0 | lhs.nCreateTime == rhs.nCreateTime && Branch (40:12): [True: 0, False: 0]
|
41 | 0 | lhs.nBanUntil == rhs.nBanUntil; Branch (41:12): [True: 0, False: 0]
|
42 | 0 | } |
43 | | |
44 | | FUZZ_TARGET(banman, .init = initialize_banman) |
45 | 0 | { |
46 | 0 | SeedRandomStateForTest(SeedRand::ZEROS); |
47 | 0 | FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; |
48 | 0 | FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)}; |
49 | 0 | fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist"; |
50 | |
|
51 | 0 | const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()}; |
52 | 0 | bool force_read_and_write_to_err{false}; |
53 | 0 | if (start_with_corrupted_banlist) { Branch (53:9): [True: 0, False: 0]
|
54 | 0 | assert(WriteBinaryFile(banlist_file + ".json", Branch (54:9): [True: 0, False: 0]
|
55 | 0 | fuzzed_data_provider.ConsumeRandomLengthString())); |
56 | 0 | } else { |
57 | 0 | force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool(); |
58 | 0 | if (force_read_and_write_to_err) { Branch (58:13): [True: 0, False: 0]
|
59 | 0 | banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist"; |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | 0 | { |
64 | 0 | BanMan ban_man{banlist_file, /*client_interface=*/nullptr, /*default_ban_time=*/ConsumeBanTimeOffset(fuzzed_data_provider)}; |
65 | | // The complexity is O(N^2), where N is the input size, because each call |
66 | | // might call DumpBanlist (or other methods that are at least linear |
67 | | // complexity of the input size). |
68 | 0 | bool contains_invalid{false}; |
69 | 0 | LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300) |
70 | 0 | { |
71 | 0 | CallOneOf( |
72 | 0 | fuzzed_data_provider, |
73 | 0 | [&] { |
74 | 0 | CNetAddr net_addr{ConsumeNetAddr(fuzzed_data_provider)}; |
75 | 0 | if (!net_addr.IsCJDNS() || !net_addr.IsValid()) { Branch (75:25): [True: 0, False: 0]
Branch (75:48): [True: 0, False: 0]
|
76 | 0 | const std::optional<CNetAddr>& addr{LookupHost(net_addr.ToStringAddr(), /*fAllowLookup=*/false)}; |
77 | 0 | if (addr.has_value() && addr->IsValid()) { Branch (77:29): [True: 0, False: 0]
Branch (77:49): [True: 0, False: 0]
|
78 | 0 | net_addr = *addr; |
79 | 0 | } else { |
80 | 0 | contains_invalid = true; |
81 | 0 | } |
82 | 0 | } |
83 | 0 | auto ban_time_offset = ConsumeBanTimeOffset(fuzzed_data_provider); |
84 | 0 | auto since_unix_epoch = fuzzed_data_provider.ConsumeBool(); |
85 | 0 | ban_man.Ban(net_addr, ban_time_offset, since_unix_epoch); |
86 | 0 | }, |
87 | 0 | [&] { |
88 | 0 | CSubNet subnet{ConsumeSubNet(fuzzed_data_provider)}; |
89 | 0 | subnet = LookupSubNet(subnet.ToString()); |
90 | 0 | if (!subnet.IsValid()) { Branch (90:25): [True: 0, False: 0]
|
91 | 0 | contains_invalid = true; |
92 | 0 | } |
93 | 0 | auto ban_time_offset = ConsumeBanTimeOffset(fuzzed_data_provider); |
94 | 0 | auto since_unix_epoch = fuzzed_data_provider.ConsumeBool(); |
95 | 0 | ban_man.Ban(subnet, ban_time_offset, since_unix_epoch); |
96 | 0 | }, |
97 | 0 | [&] { |
98 | 0 | ban_man.ClearBanned(); |
99 | 0 | }, |
100 | 0 | [&] { |
101 | 0 | ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider)); |
102 | 0 | }, |
103 | 0 | [&] { |
104 | 0 | ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider)); |
105 | 0 | }, |
106 | 0 | [&] { |
107 | 0 | ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider)); |
108 | 0 | }, |
109 | 0 | [&] { |
110 | 0 | ban_man.Unban(ConsumeSubNet(fuzzed_data_provider)); |
111 | 0 | }, |
112 | 0 | [&] { |
113 | 0 | banmap_t banmap; |
114 | 0 | ban_man.GetBanned(banmap); |
115 | 0 | }, |
116 | 0 | [&] { |
117 | 0 | ban_man.DumpBanlist(); |
118 | 0 | }, |
119 | 0 | [&] { |
120 | 0 | ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider)); |
121 | 0 | }, |
122 | 0 | [&] { |
123 | 0 | ban_man.IsDiscouraged(ConsumeNetAddr(fuzzed_data_provider)); |
124 | 0 | }); |
125 | 0 | } |
126 | 0 | if (!force_read_and_write_to_err) { Branch (126:13): [True: 0, False: 0]
|
127 | 0 | ban_man.DumpBanlist(); |
128 | 0 | clock.set(ConsumeTime(fuzzed_data_provider)); |
129 | 0 | banmap_t banmap; |
130 | 0 | ban_man.GetBanned(banmap); |
131 | 0 | BanMan ban_man_read{banlist_file, /*client_interface=*/nullptr, /*default_ban_time=*/0}; |
132 | 0 | banmap_t banmap_read; |
133 | 0 | ban_man_read.GetBanned(banmap_read); |
134 | 0 | if (!contains_invalid) { Branch (134:17): [True: 0, False: 0]
|
135 | 0 | assert(banmap == banmap_read); Branch (135:17): [True: 0, False: 0]
|
136 | 0 | } |
137 | 0 | } |
138 | 0 | } |
139 | 0 | fs::remove(fs::PathToString(banlist_file + ".json")); |
140 | 0 | } |