Coverage Report

Created: 2026-04-20 22:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}