LCOV - code coverage report
Current view: top level - src/test/fuzz - poolresource.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 100.0 % 71 71
Test Date: 2026-04-27 06:25:07 Functions: 100.0 % 82 82
Branches: 61.1 % 54 33

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2022-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 <random.h>
       6                 :             : #include <span.h>
       7                 :             : #include <support/allocators/pool.h>
       8                 :             : #include <test/fuzz/FuzzedDataProvider.h>
       9                 :             : #include <test/fuzz/fuzz.h>
      10                 :             : #include <test/fuzz/util.h>
      11                 :             : #include <test/util/poolresourcetester.h>
      12                 :             : #include <util/byte_units.h>
      13                 :             : 
      14                 :             : #include <cstdint>
      15                 :             : #include <tuple>
      16                 :             : #include <vector>
      17                 :             : 
      18                 :             : namespace {
      19                 :             : 
      20                 :             : template <std::size_t MAX_BLOCK_SIZE_BYTES, std::size_t ALIGN_BYTES>
      21                 :         721 : class PoolResourceFuzzer
      22                 :             : {
      23                 :             :     FuzzedDataProvider& m_provider;
      24                 :             :     PoolResource<MAX_BLOCK_SIZE_BYTES, ALIGN_BYTES> m_test_resource;
      25                 :             :     uint64_t m_sequence{0};
      26                 :             :     size_t m_total_allocated{};
      27                 :             : 
      28                 :             :     struct Entry {
      29                 :             :         std::span<std::byte> span;
      30                 :             :         size_t alignment;
      31                 :             :         uint64_t seed;
      32                 :             : 
      33                 :      499025 :         Entry(std::span<std::byte> s, size_t a, uint64_t se) : span(s), alignment(a), seed(se) {}
      34                 :             :     };
      35                 :             : 
      36                 :             :     std::vector<Entry> m_entries;
      37                 :             : 
      38                 :             : public:
      39                 :         721 :     PoolResourceFuzzer(FuzzedDataProvider& provider)
      40                 :         721 :         : m_provider{provider},
      41                 :         721 :           m_test_resource{provider.ConsumeIntegralInRange<size_t>(MAX_BLOCK_SIZE_BYTES, 262144)}
      42                 :             :     {
      43                 :         721 :     }
      44                 :             : 
      45                 :      499025 :     void Allocate(size_t size, size_t alignment)
      46                 :             :     {
      47         [ -  + ]:      499025 :         assert(size > 0);                           // Must allocate at least 1 byte.
      48         [ -  + ]:      499025 :         assert(alignment > 0);                      // Alignment must be at least 1.
      49         [ -  + ]:      499025 :         assert((alignment & (alignment - 1)) == 0); // Alignment must be power of 2.
      50         [ -  + ]:      499025 :         assert((size & (alignment - 1)) == 0);      // Size must be a multiple of alignment.
      51                 :             : 
      52         [ -  + ]:      499025 :         auto span = std::span(static_cast<std::byte*>(m_test_resource.Allocate(size, alignment)), size);
      53                 :      499025 :         m_total_allocated += size;
      54                 :             : 
      55                 :      499025 :         auto ptr_val = reinterpret_cast<std::uintptr_t>(span.data());
      56         [ -  + ]:      499025 :         assert((ptr_val & (alignment - 1)) == 0);
      57                 :             : 
      58                 :      499025 :         uint64_t seed = m_sequence++;
      59                 :      499025 :         RandomContentFill(m_entries.emplace_back(span, alignment, seed));
      60                 :      499025 :     }
      61                 :             : 
      62                 :             :     void
      63                 :      501871 :     Allocate()
      64                 :             :     {
      65         [ +  + ]:      501871 :         if (m_total_allocated > 16_MiB) return;
      66                 :      499025 :         size_t alignment_bits = m_provider.ConsumeIntegralInRange<size_t>(0, 7);
      67                 :      499025 :         size_t alignment = size_t{1} << alignment_bits;
      68                 :      499025 :         size_t size_bits = m_provider.ConsumeIntegralInRange<size_t>(0, 16 - alignment_bits);
      69                 :      499025 :         size_t size = m_provider.ConsumeIntegralInRange<size_t>(size_t{1} << size_bits, (size_t{1} << (size_bits + 1)) - 1U) << alignment_bits;
      70                 :      499025 :         Allocate(size, alignment);
      71                 :             :     }
      72                 :             : 
      73                 :      499025 :     void RandomContentFill(Entry& entry)
      74                 :             :     {
      75                 :      499025 :         InsecureRandomContext(entry.seed).fillrand(entry.span);
      76                 :      499025 :     }
      77                 :             : 
      78                 :      499025 :     void RandomContentCheck(const Entry& entry)
      79                 :             :     {
      80                 :      499025 :         std::vector<std::byte> expect(entry.span.size());
      81         [ -  + ]:      499025 :         InsecureRandomContext(entry.seed).fillrand(expect);
      82         [ -  + ]:      499025 :         assert(std::ranges::equal(entry.span, expect));
      83                 :      499025 :     }
      84                 :             : 
      85                 :      499025 :     void Deallocate(const Entry& entry)
      86                 :             :     {
      87         [ -  + ]:      499025 :         auto ptr_val = reinterpret_cast<std::uintptr_t>(entry.span.data());
      88         [ -  + ]:      499025 :         assert((ptr_val & (entry.alignment - 1)) == 0);
      89                 :      499025 :         RandomContentCheck(entry);
      90                 :      499025 :         m_total_allocated -= entry.span.size();
      91                 :      499025 :         m_test_resource.Deallocate(entry.span.data(), entry.span.size(), entry.alignment);
      92                 :      499025 :     }
      93                 :             : 
      94                 :      558388 :     void Deallocate()
      95                 :             :     {
      96         [ +  + ]:      558388 :         if (m_entries.empty()) {
      97                 :             :             return;
      98                 :             :         }
      99                 :             : 
     100         [ -  + ]:      499025 :         size_t idx = m_provider.ConsumeIntegralInRange<size_t>(0, m_entries.size() - 1);
     101                 :      499025 :         Deallocate(m_entries[idx]);
     102   [ -  +  +  + ]:      499025 :         if (idx != m_entries.size() - 1) {
     103                 :      495243 :             m_entries[idx] = std::move(m_entries.back());
     104                 :             :         }
     105                 :      499025 :         m_entries.pop_back();
     106                 :             :     }
     107                 :             : 
     108                 :         721 :     void Clear()
     109                 :             :     {
     110         [ +  + ]:      489697 :         while (!m_entries.empty()) {
     111                 :      488976 :             Deallocate();
     112                 :             :         }
     113                 :             : 
     114                 :         721 :         PoolResourceTester::CheckAllDataAccountedFor(m_test_resource);
     115                 :         721 :     }
     116                 :             : 
     117                 :         721 :     void Fuzz()
     118                 :             :     {
     119   [ +  +  +  + ]:      572004 :         LIMITED_WHILE(m_provider.ConsumeBool(), 10000)
     120                 :             :         {
     121                 :      571283 :             CallOneOf(
     122                 :             :                 m_provider,
     123                 :      501871 :                 [&] { Allocate(); },
     124                 :       69412 :                 [&] { Deallocate(); });
     125                 :             :         }
     126                 :         721 :         Clear();
     127                 :         721 :     }
     128                 :             : };
     129                 :             : 
     130                 :             : 
     131                 :             : } // namespace
     132                 :             : 
     133         [ +  - ]:        1179 : FUZZ_TARGET(pool_resource)
     134                 :             : {
     135                 :         721 :     FuzzedDataProvider provider(buffer.data(), buffer.size());
     136                 :         721 :     CallOneOf(
     137                 :             :         provider,
     138         [ +  - ]:         174 :         [&] { PoolResourceFuzzer<128, 1>{provider}.Fuzz(); },
     139         [ +  - ]:         170 :         [&] { PoolResourceFuzzer<128, 2>{provider}.Fuzz(); },
     140         [ +  - ]:         186 :         [&] { PoolResourceFuzzer<128, 4>{provider}.Fuzz(); },
     141         [ +  - ]:         190 :         [&] { PoolResourceFuzzer<128, 8>{provider}.Fuzz(); },
     142                 :             : 
     143         [ +  - ]:         168 :         [&] { PoolResourceFuzzer<8, 8>{provider}.Fuzz(); },
     144         [ +  - ]:         208 :         [&] { PoolResourceFuzzer<16, 16>{provider}.Fuzz(); },
     145                 :             : 
     146         [ +  - ]:         164 :         [&] { PoolResourceFuzzer<256, alignof(max_align_t)>{provider}.Fuzz(); },
     147         [ +  - ]:         182 :         [&] { PoolResourceFuzzer<256, 64>{provider}.Fuzz(); });
     148                 :         721 : }
        

Generated by: LCOV version 2.0-1