Bitcoin Core 31.99.0
P2P Digital Currency
banman.cpp
Go to the documentation of this file.
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>
9#include <test/fuzz/fuzz.h>
10#include <test/fuzz/util.h>
11#include <test/fuzz/util/net.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
23namespace {
24int64_t ConsumeBanTimeOffset(FuzzedDataProvider& fuzzed_data_provider) noexcept
25{
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 return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(std::numeric_limits<int64_t>::min(), std::numeric_limits<int32_t>::max());
29}
30} // namespace
31
33{
34 static const auto testing_setup = MakeNoLogFileContext<>();
35}
36
37static bool operator==(const CBanEntry& lhs, const CBanEntry& rhs)
38{
39 return lhs.nVersion == rhs.nVersion &&
40 lhs.nCreateTime == rhs.nCreateTime &&
41 lhs.nBanUntil == rhs.nBanUntil;
42}
43
45{
47 FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
49 fs::path banlist_file = gArgs.GetDataDirNet() / "fuzzed_banlist";
50
51 const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()};
52 bool force_read_and_write_to_err{false};
53 if (start_with_corrupted_banlist) {
54 assert(WriteBinaryFile(banlist_file + ".json",
56 } else {
57 force_read_and_write_to_err = fuzzed_data_provider.ConsumeBool();
58 if (force_read_and_write_to_err) {
59 banlist_file = fs::path{"path"} / "to" / "inaccessible" / "fuzzed_banlist";
60 }
61 }
62
63 {
64 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 bool contains_invalid{false};
70 {
73 [&] {
75 if (!net_addr.IsCJDNS() || !net_addr.IsValid()) {
76 const std::optional<CNetAddr>& addr{LookupHost(net_addr.ToStringAddr(), /*fAllowLookup=*/false)};
77 if (addr.has_value() && addr->IsValid()) {
78 net_addr = *addr;
79 } else {
80 contains_invalid = true;
81 }
82 }
83 auto ban_time_offset = ConsumeBanTimeOffset(fuzzed_data_provider);
84 auto since_unix_epoch = fuzzed_data_provider.ConsumeBool();
85 ban_man.Ban(net_addr, ban_time_offset, since_unix_epoch);
86 },
87 [&] {
89 subnet = LookupSubNet(subnet.ToString());
90 if (!subnet.IsValid()) {
91 contains_invalid = true;
92 }
93 auto ban_time_offset = ConsumeBanTimeOffset(fuzzed_data_provider);
94 auto since_unix_epoch = fuzzed_data_provider.ConsumeBool();
95 ban_man.Ban(subnet, ban_time_offset, since_unix_epoch);
96 },
97 [&] {
98 ban_man.ClearBanned();
99 },
100 [&] {
101 ban_man.IsBanned(ConsumeNetAddr(fuzzed_data_provider));
102 },
103 [&] {
104 ban_man.IsBanned(ConsumeSubNet(fuzzed_data_provider));
105 },
106 [&] {
107 ban_man.Unban(ConsumeNetAddr(fuzzed_data_provider));
108 },
109 [&] {
110 ban_man.Unban(ConsumeSubNet(fuzzed_data_provider));
111 },
112 [&] {
113 banmap_t banmap;
114 ban_man.GetBanned(banmap);
115 },
116 [&] {
117 ban_man.DumpBanlist();
118 },
119 [&] {
120 ban_man.Discourage(ConsumeNetAddr(fuzzed_data_provider));
121 },
122 [&] {
123 ban_man.IsDiscouraged(ConsumeNetAddr(fuzzed_data_provider));
124 });
125 }
126 if (!force_read_and_write_to_err) {
127 ban_man.DumpBanlist();
128 clock_ctx.set(ConsumeTime(fuzzed_data_provider));
129 banmap_t banmap;
130 ban_man.GetBanned(banmap);
131 BanMan ban_man_read{banlist_file, /*client_interface=*/nullptr, /*default_ban_time=*/0};
132 banmap_t banmap_read;
133 ban_man_read.GetBanned(banmap_read);
134 if (!contains_invalid) {
135 assert(banmap == banmap_read);
136 }
137 }
138 }
139 fs::remove(fs::PathToString(banlist_file + ".json"));
140}
ArgsManager gArgs
Definition: args.cpp:40
fs::path GetDataDirNet() const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Get data directory path with appended network identifier.
Definition: args.cpp:330
Definition: banman.h:64
void GetBanned(banmap_t &banmap) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Definition: banman.cpp:174
Definition: net_types.h:15
int64_t nCreateTime
Definition: net_types.h:19
int nVersion
Definition: net_types.h:18
int64_t nBanUntil
Definition: net_types.h:20
Network address.
Definition: netaddress.h:113
std::string ConsumeRandomLengthString(size_t max_length)
T ConsumeIntegralInRange(T min, T max)
Helper to initialize the global NodeClock, let a duration elapse, and reset it after use in a test.
Definition: time.h:40
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:162
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
Definition: fuzz.h:22
Definition: basic.cpp:8
std::map< CSubNet, CBanEntry > banmap_t
Definition: net_types.h:41
CSubNet LookupSubNet(const std::string &subnet_str)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:814
std::vector< CNetAddr > LookupHost(const std::string &name, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
Resolve a host string to its corresponding network addresses.
Definition: netbase.cpp:173
bool WriteBinaryFile(const fs::path &filename, const std::string &data)
Write contents of std::string to a file.
void initialize_banman()
Definition: banman.cpp:32
FUZZ_TARGET(banman,.init=initialize_banman)
Definition: banman.cpp:44
static bool operator==(const CBanEntry &lhs, const CBanEntry &rhs)
Definition: banman.cpp:37
CNetAddr ConsumeNetAddr(FuzzedDataProvider &fuzzed_data_provider, FastRandomContext *rand) noexcept
Create a CNetAddr.
Definition: net.cpp:29
CSubNet ConsumeSubNet(FuzzedDataProvider &fuzzed_data_provider) noexcept
Definition: net.h:245
NodeSeconds ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
Definition: util.cpp:34
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
Definition: util.h:35
void SeedRandomStateForTest(SeedRand seedtype)
Seed the global RNG state for testing and log the seed value.
Definition: random.cpp:19
@ ZEROS
Seed with a compile time constant of zeros.
assert(!tx.IsCoinBase())
FuzzedDataProvider & fuzzed_data_provider
Definition: fees.cpp:39