• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 20606765815

30 Dec 2025 06:57PM UTC coverage: 90.423% (-0.002%) from 90.425%
20606765815

push

github

web-flow
Merge pull request #5200 from randombit/jack/newton-for-monty-inverse

Use Newton's method for computing monty_inverse

101645 of 112411 relevant lines covered (90.42%)

12929510.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.21
/src/fuzzer/mem_pool.cpp
1
/*
2
* (C) 2018 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "fuzzers.h"
8

9
#include <botan/internal/bit_ops.h>
10
#include <botan/internal/mem_pool.h>
11
#include <cstring>
12
#include <map>
13
#include <utility>
14
#include <vector>
15

16
#include <cstdlib>
17

18
namespace {
19

20
size_t compute_expected_alignment(size_t plen) {
103,182✔
21
   if(Botan::is_power_of_2(plen)) {
305,289✔
22
      return plen;
23
   } else {
24
      return 8;
98,925✔
25
   }
26
}
27

28
struct RawPage {
29
   public:
30
      explicit RawPage(void* p) : m_p(p) {}
4✔
31

32
      ~RawPage() {
8✔
33
         // NOLINTNEXTLINE(*-no-malloc,*-owning-memory)
34
         std::free(m_p);
8✔
35
      }
4✔
36

37
      RawPage(const RawPage& other) = default;
38
      RawPage& operator=(const RawPage& other) = default;
39

40
      RawPage(RawPage&& other) noexcept : m_p(nullptr) { std::swap(m_p, other.m_p); }
4✔
41

42
      RawPage& operator=(RawPage&& other) noexcept {
43
         if(this != &other) {
44
            std::swap(m_p, other.m_p);
45
         }
46
         return (*this);
47
      }
48

49
      void* ptr() const { return m_p; }
4,000✔
50

51
   private:
52
      void* m_p;
53
};
54

55
std::vector<RawPage> allocate_raw_pages(size_t count, size_t page_size) {
1✔
56
   std::vector<RawPage> pages;
1✔
57
   pages.reserve(count);
1✔
58

59
   for(size_t i = 0; i != count; ++i) {
5✔
60
      void* ptr = nullptr;
4✔
61

62
      const int rc = ::posix_memalign(&ptr, page_size, page_size);
4✔
63
      FUZZER_ASSERT_EQUAL(rc, 0);
4✔
64

65
      if(ptr != nullptr) {
4✔
66
         pages.push_back(RawPage(ptr));
4✔
67
      }
68
   }
69

70
   return pages;
1✔
71
}
×
72

73
}  // namespace
74

75
void fuzz(std::span<const uint8_t> in) {
1,000✔
76
   const size_t page_count = 4;
1,000✔
77
   const size_t page_size = 4096;
1,000✔
78

79
   // static to avoid repeated allocations
80
   static const std::vector<RawPage> raw_mem = allocate_raw_pages(page_count, page_size);
1,000✔
81

82
   std::vector<void*> mem_pages;
1,000✔
83
   mem_pages.reserve(raw_mem.size());
1,000✔
84
   for(const auto& rm : raw_mem) {
5,000✔
85
      mem_pages.push_back(rm.ptr());
4,000✔
86
   }
87

88
   Botan::Memory_Pool pool(mem_pages, page_size);
1,000✔
89
   std::map<uint8_t*, size_t> ptrs;
1,000✔
90

91
   size_t in_len = in.size();
1,000✔
92
   const auto* x = in.data();
1,000✔
93
   while(in_len > 0) {
493,844✔
94
      const uint8_t op = in[0] % 2;
492,844✔
95
      size_t idx = (in[0] >> 1);
492,844✔
96
      x += 1;
492,844✔
97
      in_len -= 1;
492,844✔
98

99
      if(in_len > 0 && idx < 4) {
492,844✔
100
         idx = idx * 256 + x[0];
6,656✔
101
         x += 1;
6,656✔
102
         in_len -= 1;
6,656✔
103
      }
104

105
      if(op == 0) {
492,844✔
106
         const size_t plen = idx + 1;  // ensure non-zero
262,419✔
107
         uint8_t* p = static_cast<uint8_t*>(pool.allocate(plen));
262,419✔
108

109
         if(p != nullptr) {
262,419✔
110
            const size_t expected_alignment = compute_expected_alignment(plen);
103,182✔
111
            const size_t alignment = reinterpret_cast<uintptr_t>(p) % expected_alignment;
103,182✔
112
            if(alignment != 0) {
103,182✔
113
               FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer "
×
114
                                      << static_cast<void*>(p) << " for len " << plen << " expected "
115
                                      << expected_alignment << " got " << alignment);
116
            }
117

118
            //printf("alloc %d -> %p\n", plen, p);
119

120
            for(size_t i = 0; i != plen; ++i) {
6,132,179✔
121
               if(p[i] != 0) {
6,028,997✔
122
                  FUZZER_WRITE_AND_CRASH("Pool gave out non-zeroed memory");
6,028,997✔
123
               }
124
            }
125

126
            // verify it becomes zeroed later
127
            std::memset(p, static_cast<int>(idx), plen);
103,182✔
128

129
            auto insert = ptrs.insert(std::make_pair(p, plen));
103,182✔
130
            if(!insert.second) {
103,182✔
131
               FUZZER_WRITE_AND_CRASH("Pointer " << static_cast<void*>(p) << " already existed\n");
×
132
            }
133

134
            auto itr = insert.first;
103,182✔
135

136
            // Verify this pointer doesn't overlap with the one before it
137
            if(itr != ptrs.begin()) {
103,182✔
138
               auto before = std::prev(itr);
102,705✔
139
               auto ptr_before = *before;
102,705✔
140

141
               if(ptr_before.first + ptr_before.second > p) {
102,705✔
142
                  FUZZER_WRITE_AND_CRASH("Previous " << static_cast<void*>(ptr_before.first) << "/" << ptr_before.second
×
143
                                                     << " overlaps with new " << static_cast<void*>(p));
144
               }
145
            }
146

147
            auto after = std::next(itr);
103,182✔
148

149
            if(after != ptrs.end()) {
103,182✔
150
               if(p + plen > after->first) {
×
151
                  FUZZER_WRITE_AND_CRASH("New " << static_cast<void*>(p) << "/" << plen << " overlaps following "
×
152
                                                << static_cast<void*>(after->first));
153
               }
154
            }
155
         }
156
      } else if(op == 1) {
230,425✔
157
         if(ptrs.empty()) {
230,425✔
158
            continue;
230,425✔
159
         }
160

161
         size_t which_ptr = idx % ptrs.size();
×
162

163
         auto itr = ptrs.begin();
×
164

165
         while(which_ptr-- > 0) {
×
166
            ++itr;
×
167
         }
168

169
         //printf("free %p %d\n", itr->first, itr->second);
170
         FUZZER_ASSERT_TRUE(pool.deallocate(itr->first, itr->second));
×
171
         ptrs.erase(itr);
×
172
      }
173
   }
174
}
1,000✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc