LCOV - code coverage report
Current view: top level - src/test/fuzz - addrman.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 99.3 % 144 143
Test Date: 2026-11-13 06:27:04 Functions: 100.0 % 16 16
Branches: 64.8 % 182 118

             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                 :             : 
       7                 :             : #include <addrdb.h>
       8                 :             : #include <addrman_impl.h>
       9                 :             : #include <chainparams.h>
      10                 :             : #include <common/args.h>
      11                 :             : #include <merkleblock.h>
      12                 :             : #include <random.h>
      13                 :             : #include <test/fuzz/FuzzedDataProvider.h>
      14                 :             : #include <test/fuzz/fuzz.h>
      15                 :             : #include <test/fuzz/util.h>
      16                 :             : #include <test/fuzz/util/net.h>
      17                 :             : #include <test/util/setup_common.h>
      18                 :             : #include <test/util/time.h>
      19                 :             : #include <util/asmap.h>
      20                 :             : #include <util/chaintype.h>
      21                 :             : #include <util/check.h>
      22                 :             : 
      23                 :             : #include <cstdint>
      24                 :             : #include <ctime>
      25                 :             : #include <optional>
      26                 :             : #include <string>
      27                 :             : #include <vector>
      28                 :             : 
      29                 :             : namespace {
      30                 :             : const BasicTestingSetup* g_setup;
      31                 :             : 
      32                 :        6309 : int32_t GetCheckRatio()
      33                 :             : {
      34         [ +  - ]:       18927 :     return std::clamp<int32_t>(g_setup->m_node.args->GetIntArg("-checkaddrman", 0), 0, 1000000);
      35                 :             : }
      36                 :             : } // namespace
      37                 :             : 
      38                 :           3 : void initialize_addrman()
      39                 :             : {
      40   [ +  -  +  -  :           3 :     static const auto testing_setup = MakeNoLogFileContext<>(ChainType::REGTEST);
                   +  - ]
      41                 :           3 :     g_setup = testing_setup.get();
      42                 :           3 : }
      43                 :             : 
      44         [ +  - ]:        1672 : FUZZ_TARGET(data_stream_addr_man, .init = initialize_addrman)
      45                 :             : {
      46                 :        1196 :     SeedRandomStateForTest(SeedRand::ZEROS);
      47                 :        1196 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
      48                 :        1196 :     DataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
      49                 :        1196 :     NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
      50   [ +  -  +  - ]:        1196 :     AddrMan addr_man(netgroupman, /*deterministic=*/false, GetCheckRatio());
      51                 :        1196 :     try {
      52         [ +  + ]:        1196 :         ReadFromStream(addr_man, data_stream);
      53         [ -  + ]:         732 :     } catch (const std::exception&) {
      54                 :         732 :     }
      55                 :        1196 : }
      56                 :             : 
      57                 :             : /**
      58                 :             :  * Generate a random address. Always returns a valid address.
      59                 :             :  */
      60                 :     8817407 : CNetAddr RandAddr(FuzzedDataProvider& fuzzed_data_provider, FastRandomContext& fast_random_context)
      61                 :             : {
      62                 :     8817407 :     CNetAddr addr;
      63   [ +  -  +  - ]:     8817407 :     assert(!addr.IsValid());
      64   [ +  +  +  -  :    19309050 :     for (size_t i = 0; i < 8 && !addr.IsValid(); ++i) {
                   +  + ]
      65   [ +  +  +  + ]:    11854228 :         if (fuzzed_data_provider.remaining_bytes() > 1 && fuzzed_data_provider.ConsumeBool()) {
      66                 :     1056665 :             addr = ConsumeNetAddr(fuzzed_data_provider);
      67                 :             :         } else {
      68                 :     9434978 :             addr = ConsumeNetAddr(fuzzed_data_provider, &fast_random_context);
      69                 :             :         }
      70                 :             :     }
      71                 :             : 
      72                 :             :     // Return a dummy IPv4 5.5.5.5 if we generated an invalid address.
      73   [ +  -  +  + ]:     8817407 :     if (!addr.IsValid()) {
      74                 :        5582 :         in_addr v4_addr = {};
      75                 :        5582 :         v4_addr.s_addr = 0x05050505;
      76         [ +  - ]:       11164 :         addr = CNetAddr{v4_addr};
      77                 :             :     }
      78                 :             : 
      79                 :     8817407 :     return addr;
      80                 :           0 : }
      81                 :             : 
      82                 :             : /** Fill addrman with lots of addresses from lots of sources.  */
      83                 :        1272 : void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
      84                 :             : {
      85                 :             :     // Add a fraction of the addresses to the "tried" table.
      86                 :             :     // 0, 1, 2, 3 corresponding to 0%, 100%, 50%, 33%
      87                 :        1272 :     const size_t n = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 3);
      88                 :             : 
      89                 :        1272 :     const size_t num_sources = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 50);
      90                 :        1272 :     CNetAddr prev_source;
      91                 :             :     // Generate a FastRandomContext seed to use inside the loops instead of
      92                 :             :     // fuzzed_data_provider. When fuzzed_data_provider is exhausted it
      93                 :             :     // just returns 0.
      94                 :        1272 :     FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
      95         [ +  + ]:       36345 :     for (size_t i = 0; i < num_sources; ++i) {
      96         [ +  - ]:       35073 :         const auto source = RandAddr(fuzzed_data_provider, fast_random_context);
      97                 :       35073 :         const size_t num_addresses = fast_random_context.randrange(500) + 1; // [1..500]
      98                 :             : 
      99         [ +  + ]:     8817407 :         for (size_t j = 0; j < num_addresses; ++j) {
     100   [ +  -  +  - ]:    17564668 :             const auto addr = CAddress{CService{RandAddr(fuzzed_data_provider, fast_random_context), 8333}, NODE_NETWORK};
     101                 :     8782334 :             const std::chrono::seconds time_penalty{fast_random_context.randrange(100000001)};
     102   [ +  -  +  -  :    17564668 :             addrman.Add({addr}, source, time_penalty);
             +  +  -  - ]
     103                 :             : 
     104   [ +  +  +  -  :     8782334 :             if (n > 0 && addrman.Size() % n == 0) {
                   +  + ]
     105         [ +  - ]:     5143001 :                 addrman.Good(addr, Now<NodeSeconds>());
     106                 :             :             }
     107                 :             : 
     108                 :             :             // Add 10% of the addresses from more than one source.
     109   [ +  +  +  -  :     8782334 :             if (fast_random_context.randrange(10) == 0 && prev_source.IsValid()) {
                   +  + ]
     110   [ +  -  +  -  :     1710742 :                 addrman.Add({addr}, prev_source, time_penalty);
             +  +  -  - ]
     111                 :             :             }
     112                 :     8782334 :         }
     113                 :       35073 :         prev_source = source;
     114                 :       35073 :     }
     115                 :     9638977 : }
     116                 :             : 
     117         [ +  - ]:        2260 : FUZZ_TARGET(addrman, .init = initialize_addrman)
     118                 :             : {
     119                 :        1784 :     SeedRandomStateForTest(SeedRand::ZEROS);
     120                 :        1784 :     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
     121                 :        1784 :     FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)};
     122                 :        1784 :     NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
     123   [ +  -  +  - ]:        1784 :     auto addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
     124         [ +  + ]:        1784 :     if (fuzzed_data_provider.ConsumeBool()) {
     125                 :        1076 :         const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
     126   [ -  +  +  - ]:        1076 :         DataStream ds{serialized_data};
     127                 :        1076 :         try {
     128         [ +  + ]:        2152 :             ds >> *addr_man_ptr;
     129         [ -  + ]:         785 :         } catch (const std::ios_base::failure&) {
     130   [ +  -  +  - ]:        1570 :             addr_man_ptr = std::make_unique<AddrManDeterministic>(netgroupman, fuzzed_data_provider, GetCheckRatio());
     131                 :         785 :         }
     132                 :        1076 :     }
     133                 :        1784 :     AddrManDeterministic& addr_man = *addr_man_ptr;
     134   [ +  +  +  + ]:      493803 :     LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 10000) {
     135         [ +  - ]:      492019 :         CallOneOf(
     136                 :             :             fuzzed_data_provider,
     137                 :        8652 :             [&] {
     138                 :        8652 :                 addr_man.ResolveCollisions();
     139                 :        8652 :             },
     140                 :       70661 :             [&] {
     141                 :       70661 :                 (void)addr_man.SelectTriedCollision();
     142                 :       70661 :             },
     143                 :       10051 :             [&] {
     144                 :       10051 :                 std::vector<CAddress> addresses;
     145   [ +  +  +  + ]:     2677610 :                 LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 10000) {
     146         [ +  - ]:     2667559 :                     addresses.push_back(ConsumeAddress(fuzzed_data_provider));
     147                 :             :                 }
     148                 :       10051 :                 auto net_addr = ConsumeNetAddr(fuzzed_data_provider);
     149                 :       10051 :                 auto time_penalty = ConsumeDuration<std::chrono::seconds>(fuzzed_data_provider, /*min=*/0s, /*max=*/100000000s);
     150         [ +  - ]:       10051 :                 addr_man.Add(addresses, net_addr, time_penalty);
     151                 :       10051 :             },
     152                 :      335466 :             [&] {
     153                 :      335466 :                 auto addr = ConsumeService(fuzzed_data_provider);
     154                 :      335466 :                 auto time = ConsumeTime(fuzzed_data_provider);
     155         [ +  - ]:      335466 :                 addr_man.Good(addr, time);
     156                 :      335466 :             },
     157                 :        7585 :             [&] {
     158                 :        7585 :                 auto addr = ConsumeService(fuzzed_data_provider);
     159                 :        7585 :                 auto count_failure = fuzzed_data_provider.ConsumeBool();
     160                 :        7585 :                 auto time = ConsumeTime(fuzzed_data_provider);
     161         [ +  - ]:        7585 :                 addr_man.Attempt(addr, count_failure, time);
     162                 :        7585 :             },
     163                 :        9462 :             [&] {
     164                 :        9462 :                 auto addr = ConsumeService(fuzzed_data_provider);
     165                 :        9462 :                 auto time = ConsumeTime(fuzzed_data_provider);
     166         [ +  - ]:        9462 :                 addr_man.Connected(addr, time);
     167                 :        9462 :             },
     168                 :       50142 :             [&] {
     169                 :       50142 :                 auto addr = ConsumeService(fuzzed_data_provider);
     170                 :       50142 :                 auto n_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
     171         [ +  - ]:       50142 :                 addr_man.SetServices(addr, n_services);
     172                 :       50142 :             });
     173                 :             :     }
     174                 :        1784 :     const AddrMan& const_addr_man{addr_man};
     175                 :        1784 :     std::optional<Network> network;
     176         [ +  + ]:        1784 :     if (fuzzed_data_provider.ConsumeBool()) {
     177                 :         164 :         network = fuzzed_data_provider.PickValueInArray(ALL_NETWORKS);
     178                 :             :     }
     179                 :        1784 :     auto max_addresses = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
     180                 :        1784 :     auto max_pct = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 100);
     181                 :        1784 :     auto filtered = fuzzed_data_provider.ConsumeBool();
     182         [ +  - ]:        1784 :     (void)const_addr_man.GetAddr(max_addresses, max_pct, network, filtered);
     183                 :             : 
     184                 :        1784 :     std::unordered_set<Network> nets;
     185         [ +  + ]:       14272 :     for (const auto& net : ALL_NETWORKS) {
     186         [ +  + ]:       12488 :         if (fuzzed_data_provider.ConsumeBool()) {
     187         [ +  - ]:        1128 :             nets.insert(net);
     188                 :             :         }
     189                 :             :     }
     190                 :        1784 :     const bool new_only{fuzzed_data_provider.ConsumeBool()};
     191         [ +  - ]:        1784 :     const CAddress selected{const_addr_man.Select(new_only, nets).first};
     192                 :             :     // Select() must return a (valid) address if and only if there are entries matching the
     193                 :             :     // filters, and if a network filter was provided, the selected address must match it.
     194         [ +  + ]:        1784 :     const std::optional<bool> select_in_new{new_only ? std::optional<bool>{true} : std::nullopt};
     195                 :        1784 :     size_t num_matching{0};
     196         [ +  + ]:        1784 :     if (nets.empty()) {
     197         [ +  - ]:        1526 :         num_matching = const_addr_man.Size(/*net=*/std::nullopt, select_in_new);
     198                 :             :     } else {
     199   [ +  +  +  - ]:        1386 :         for (const auto net : nets) num_matching += const_addr_man.Size(net, select_in_new);
     200                 :             :     }
     201   [ +  -  -  + ]:        1784 :     assert(selected.IsValid() == (num_matching > 0));
     202   [ +  +  +  -  :        1784 :     if (!nets.empty() && selected.IsValid()) assert(nets.contains(selected.GetNetwork()));
          +  +  +  -  -  
                      + ]
     203                 :             : 
     204                 :        1784 :     std::optional<bool> in_new;
     205         [ +  + ]:        1784 :     if (fuzzed_data_provider.ConsumeBool()) {
     206                 :         150 :         in_new = fuzzed_data_provider.ConsumeBool();
     207                 :             :     }
     208         [ +  - ]:        1784 :     (void)const_addr_man.Size(network, in_new);
     209                 :        1784 :     DataStream data_stream{};
     210         [ +  - ]:        3568 :     data_stream << const_addr_man;
     211                 :        1784 : }
     212                 :             : 
     213                 :             : // Check that serialize followed by unserialize produces the same addrman.
     214         [ +  - ]:        1748 : FUZZ_TARGET(addrman_serdeser, .init = initialize_addrman)
     215                 :             : {
     216                 :        1272 :     SeedRandomStateForTest(SeedRand::ZEROS);
     217                 :        1272 :     FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
     218                 :        1272 :     FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)};
     219                 :             : 
     220                 :        1272 :     NetGroupManager netgroupman{ConsumeNetGroupManager(fuzzed_data_provider)};
     221   [ +  -  +  - ]:        1272 :     AddrManDeterministic addr_man1{netgroupman, fuzzed_data_provider, GetCheckRatio()};
     222   [ +  -  +  - ]:        1272 :     AddrManDeterministic addr_man2{netgroupman, fuzzed_data_provider, GetCheckRatio()};
     223                 :             : 
     224                 :        1272 :     DataStream data_stream{};
     225                 :             : 
     226         [ +  - ]:        1272 :     FillAddrman(addr_man1, fuzzed_data_provider);
     227         [ +  - ]:        1272 :     data_stream << addr_man1;
     228         [ +  - ]:        1272 :     data_stream >> addr_man2;
     229   [ +  -  -  + ]:        1272 :     assert(addr_man1 == addr_man2);
     230                 :        1272 : }
        

Generated by: LCOV version 2.5.0-full