Coverage Report

Created: 2023-02-13 06:21

/src/botan/src/fuzzer/mem_pool.cpp
Line
Count
Source (jump to first uncovered line)
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
#include <botan/internal/mem_pool.h>
9
#include <botan/internal/bit_ops.h>
10
#include <vector>
11
#include <map>
12
#include <utility>
13
14
#include <cstdlib>
15
16
namespace {
17
18
size_t compute_expected_alignment(size_t plen)
19
136k
   {
20
136k
   if(Botan::is_power_of_2(plen))
21
84.0k
      {
22
84.0k
      return plen;
23
84.0k
      }
24
52.5k
   else
25
52.5k
      {
26
52.5k
      return 8;
27
52.5k
      }
28
136k
   }
29
30
struct RawPage
31
   {
32
   public:
33
4
      RawPage(void* p) : m_p(p) {}
34
8
      ~RawPage() { std::free(m_p); }
35
36
      RawPage(const RawPage& other) = default;
37
      RawPage& operator=(const RawPage& other) = default;
38
39
      RawPage(RawPage&& other) : m_p(nullptr)
40
4
         {
41
4
         std::swap(m_p, other.m_p);
42
4
         }
43
44
      RawPage& operator=(RawPage&& other)
45
0
         {
46
0
         if(this != &other)
47
0
            {
48
0
            std::swap(m_p, other.m_p);
49
0
            }
50
0
         return (*this);
51
0
         }
52
53
4.71k
      void* ptr() const { return m_p; }
54
   private:
55
      void* m_p;
56
   };
57
58
std::vector<RawPage> allocate_raw_pages(size_t count, size_t page_size)
59
1
   {
60
1
   std::vector<RawPage> pages;
61
1
   pages.reserve(count);
62
63
5
   for(size_t i = 0; i != count; ++i)
64
4
      {
65
4
      void* ptr = nullptr;
66
67
4
      int rc = ::posix_memalign(&ptr, page_size, page_size);
68
4
      FUZZER_ASSERT_EQUAL(rc, 0);
69
70
4
      if(ptr)
71
4
         {
72
4
         pages.push_back(RawPage(ptr));
73
4
         }
74
4
      }
75
76
1
   return pages;
77
1
   }
78
79
}
80
81
void fuzz(const uint8_t in[], size_t in_len)
82
1.17k
   {
83
1.17k
   const size_t page_count = 4;
84
1.17k
   const size_t page_size = 4096;
85
86
   // static to avoid repeated allocations
87
1.17k
   static std::vector<RawPage> raw_mem = allocate_raw_pages(page_count, page_size);
88
89
1.17k
   std::vector<void*> mem_pages;
90
1.17k
   mem_pages.reserve(raw_mem.size());
91
5.89k
   for(size_t i = 0; i != raw_mem.size(); ++i)
92
4.71k
      mem_pages.push_back(raw_mem[i].ptr());
93
94
1.17k
   Botan::Memory_Pool pool(mem_pages, page_size);
95
1.17k
   std::map<uint8_t*, size_t> ptrs;
96
97
262k
   while(in_len > 0)
98
261k
      {
99
261k
      const uint8_t op = in[0] % 2;
100
261k
      size_t idx = (in[0] >> 1);
101
261k
      in += 1;
102
261k
      in_len -= 1;
103
104
261k
      if(in_len > 0 && idx < 4)
105
8.23k
         {
106
8.23k
         idx = idx * 256 + in[0];
107
8.23k
         in += 1;
108
8.23k
         in_len -= 1;
109
8.23k
         }
110
111
261k
      if(op == 0)
112
150k
         {
113
150k
         const size_t plen = idx + 1; // ensure non-zero
114
150k
         uint8_t* p = static_cast<uint8_t*>(pool.allocate(plen));
115
116
150k
         if(p)
117
136k
            {
118
136k
            const size_t expected_alignment = compute_expected_alignment(plen);
119
136k
            const size_t alignment = reinterpret_cast<uintptr_t>(p) % expected_alignment;
120
136k
            if(alignment != 0)
121
0
               {
122
0
               FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer " << static_cast<void*>(p) << " for len " << plen
123
0
                                      << " expected " << expected_alignment << " got " << alignment);
124
0
               }
125
126
            //printf("alloc %d -> %p\n", plen, p);
127
128
6.82M
            for(size_t i = 0; i != plen; ++i)
129
6.68M
               {
130
6.68M
               if(p[i] != 0)
131
0
                  {
132
0
                  FUZZER_WRITE_AND_CRASH("Pool gave out non-zeroed memory");
133
0
                  }
134
6.68M
               }
135
136
            // verify it becomes zeroed later
137
136k
            std::memset(p, static_cast<int>(idx), plen);
138
139
136k
            auto insert = ptrs.insert(std::make_pair(p, plen));
140
136k
            if(insert.second == false)
141
0
               {
142
0
               FUZZER_WRITE_AND_CRASH("Pointer " << static_cast<void*>(p) << " already existed\n");
143
0
               }
144
145
136k
            auto itr = insert.first;
146
147
            // Verify this pointer doesn't overlap with the one before it
148
136k
            if(itr != ptrs.begin())
149
81.7k
               {
150
81.7k
               auto before = std::prev(itr);
151
81.7k
               auto ptr_before = *before;
152
153
81.7k
               if(ptr_before.first + ptr_before.second > p)
154
0
                  {
155
0
                  FUZZER_WRITE_AND_CRASH("Previous " << static_cast<void*>(ptr_before.first) << "/" << ptr_before.second <<
156
0
                                         " overlaps with new " << static_cast<void*>(p));
157
0
                  }
158
81.7k
               }
159
160
136k
            auto after = std::next(itr);
161
162
136k
            if(after != ptrs.end())
163
58.0k
               {
164
58.0k
               if(p + plen > after->first)
165
0
                  {
166
0
                  FUZZER_WRITE_AND_CRASH("New " << static_cast<void*>(p) << "/" << plen
167
0
                                         << " overlaps following " << static_cast<void*>(after->first));
168
0
                  }
169
58.0k
               }
170
136k
            }
171
150k
         }
172
110k
      else if(op == 1)
173
110k
         {
174
110k
         if(ptrs.empty())
175
4.02k
            continue;
176
177
106k
         size_t which_ptr = idx % ptrs.size();
178
179
106k
         auto itr = ptrs.begin();
180
181
1.06M
         while(which_ptr-- > 0)
182
961k
            {
183
961k
            ++itr;
184
961k
            }
185
186
         //printf("free %p %d\n", itr->first, itr->second);
187
106k
         FUZZER_ASSERT_TRUE(pool.deallocate(itr->first, itr->second));
188
106k
         ptrs.erase(itr);
189
106k
         }
190
261k
      }
191
1.17k
   }