/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 | 28.7k | { |
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 | 28.7k | return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::max()); |
29 | 28.7k | } |
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 | 6.34k | { |
39 | 6.34k | return lhs.nVersion == rhs.nVersion && |
40 | 6.34k | lhs.nCreateTime == rhs.nCreateTime && |
41 | 6.34k | lhs.nBanUntil == rhs.nBanUntil; |
42 | 6.34k | } |
43 | | |
44 | | FUZZ_TARGET(banman, .init = initialize_banman) |
45 | 1.56k | { |
46 | 1.56k | SeedRandomStateForTest(SeedRand::ZEROS); |
47 | 1.56k | FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; |
48 | 1.56k | NodeClockContext clock_ctx{ConsumeTime(fuzzed_data_provider)}; |
49 | 1.56k | fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist"; |
50 | | |
51 | 1.56k | const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()}; |
52 | 1.56k | bool force_read_and_write_to_err{false}; |
53 | 1.56k | if (start_with_corrupted_banlist) { |
54 | 1.05k | assert(WriteBinaryFile(banlist_file + ".json", |
55 | 1.05k | fuzzed_data_provider.ConsumeRandomLengthString())); |
56 | 1.05k | } else { |
57 | 510 | force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool(); |
58 | 510 | if (force_read_and_write_to_err) { |
59 | 155 | banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist"; |
60 | 155 | } |
61 | 510 | } |
62 | | |
63 | 1.56k | { |
64 | 1.56k | 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 | 1.56k | bool contains_invalid{false}; |
69 | 1.56k | LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 300) |
70 | 53.9k | { |
71 | 53.9k | CallOneOf( |
72 | 53.9k | fuzzed_data_provider, |
73 | 53.9k | [&] { |
74 | 22.8k | CNetAddr net_addr{ConsumeNetAddr(fuzzed_data_provider)}; |
75 | 22.8k | if (!net_addr.IsCJDNS() || !net_addr.IsValid()) { |
76 | 21.8k | const std::optional<CNetAddr>& addr{LookupHost(net_addr.ToStringAddr(), /*fAllowLookup=*/false)}; |
77 | 21.8k | if (addr.has_value() && addr->IsValid()) { |
78 | 18.4k | net_addr = *addr; |
79 | 18.4k | } else { |
80 | 3.36k | contains_invalid = true; |
81 | 3.36k | } |
82 | 21.8k | } |
83 | 22.8k | auto ban_time_offset = ConsumeBanTimeOffset(fuzzed_data_provider); |
84 | 22.8k | auto since_unix_epoch = fuzzed_data_provider.ConsumeBool(); |
85 | 22.8k | ban_man.Ban(net_addr, ban_time_offset, since_unix_epoch); |
86 | 22.8k | }, |
87 | 53.9k | [&] { |
88 | 4.33k | CSubNet subnet{ConsumeSubNet(fuzzed_data_provider)}; |
89 | 4.33k | subnet = LookupSubNet(subnet.ToString()); |
90 | 4.33k | if (!subnet.IsValid()) { |
91 | 31 | contains_invalid = true; |
92 | 31 | } |
93 | 4.33k | auto ban_time_offset = ConsumeBanTimeOffset(fuzzed_data_provider); |
94 | 4.33k | auto since_unix_epoch = fuzzed_data_provider.ConsumeBool(); |
95 | 4.33k | ban_man.Ban(subnet, ban_time_offset, since_unix_epoch); |
96 | 4.33k | }, |
97 | 53.9k | [&] { |
98 | 3.25k | ban_man.ClearBanned(); |
99 | 3.25k | }, |
100 | 53.9k | [&] { |
101 | 3.72k | ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider)); |
102 | 3.72k | }, |
103 | 53.9k | [&] { |
104 | 2.96k | ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider)); |
105 | 2.96k | }, |
106 | 53.9k | [&] { |
107 | 3.56k | ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider)); |
108 | 3.56k | }, |
109 | 53.9k | [&] { |
110 | 1.58k | ban_man.Unban(ConsumeSubNet(fuzzed_data_provider)); |
111 | 1.58k | }, |
112 | 53.9k | [&] { |
113 | 1.33k | banmap_t banmap; |
114 | 1.33k | ban_man.GetBanned(banmap); |
115 | 1.33k | }, |
116 | 53.9k | [&] { |
117 | 3.66k | ban_man.DumpBanlist(); |
118 | 3.66k | }, |
119 | 53.9k | [&] { |
120 | 2.50k | ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider)); |
121 | 2.50k | }, |
122 | 53.9k | [&] { |
123 | 4.15k | ban_man.IsDiscouraged(ConsumeNetAddr(fuzzed_data_provider)); |
124 | 4.15k | }); |
125 | 53.9k | } |
126 | 1.56k | if (!force_read_and_write_to_err) { |
127 | 1.41k | ban_man.DumpBanlist(); |
128 | 1.41k | clock_ctx.set(ConsumeTime(fuzzed_data_provider)); |
129 | 1.41k | banmap_t banmap; |
130 | 1.41k | ban_man.GetBanned(banmap); |
131 | 1.41k | BanMan ban_man_read{banlist_file, /*client_interface=*/nullptr, /*default_ban_time=*/0}; |
132 | 1.41k | banmap_t banmap_read; |
133 | 1.41k | ban_man_read.GetBanned(banmap_read); |
134 | 1.41k | if (!contains_invalid) { |
135 | 1.19k | assert(banmap == banmap_read); |
136 | 1.19k | } |
137 | 1.41k | } |
138 | 1.56k | } |
139 | 1.56k | fs::remove(fs::PathToString(banlist_file + ".json")); |
140 | 1.56k | } |