aboutsummaryrefslogtreecommitdiffstats
path: root/src/fuzzer/mem_pool.cpp
blob: 40706bae17cccd82b494c1280e3e280c9e5f1f12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
* (C) 2018 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "fuzzers.h"
#include <botan/internal/mem_pool.h>
#include <vector>
#include <map>
#include <utility>

void fuzz(const uint8_t in[], size_t in_len)
   {
   const size_t page_size = 4096;
   const size_t pages = 4;
   const size_t expected_alignment = (1 << 4);

   static std::vector<uint8_t> raw_mem(page_size * pages);

   Botan::Memory_Pool pool(raw_mem.data(), raw_mem.size(), page_size, 1, 128, 4);
   std::map<uint8_t*, size_t> ptrs;

   while(in_len > 0)
      {
      const uint8_t op = in[0] % 1;
      size_t idx = (in[0] >> 1);
      in += 1;
      in_len -= 1;

      if(in_len > 0 && idx < 4)
         {
         idx = idx * 256 + in[0];
         in += 1;
         in_len -= 1;
         }

      if(op == 0)
         {
         const size_t plen = idx + 1; // ensure non-zero
         uint8_t* p = static_cast<uint8_t*>(pool.allocate(plen));

         if(reinterpret_cast<uintptr_t>(p) % expected_alignment != 0)
            {
            FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer " << p);
            }

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

            for(size_t i = 0; i != plen; ++i)
               {
               if(p[i] != 0)
                  {
                  FUZZER_WRITE_AND_CRASH("Pool gave out non-zeroed memory");
                  }
               }

            // verify it becomes zeroed later
            std::memset(p, idx, plen);

            auto insert = ptrs.insert(std::make_pair(p, plen));
            if(insert.second == false)
               {
               FUZZER_WRITE_AND_CRASH("Pointer " << p << " already existed\n");
               }

            auto itr = insert.first;

            // Verify this pointer doesn't overlap with the one before it
            if(itr != ptrs.begin())
               {
               auto before = std::prev(itr);
               auto ptr_before = *before;

               if(ptr_before.first + ptr_before.second > p)
                  {
                  FUZZER_WRITE_AND_CRASH("Previous " << ptr_before.first << "/" << ptr_before.second <<
                                         " overlaps with new " << p);
                  }
               }

            auto after = std::next(itr);

            if(after != ptrs.end())
               {
               if(p + plen > after->first)
                  {
                  FUZZER_WRITE_AND_CRASH("New " << p << "/" << plen << " overlaps following " << after->first);
                  }
               }
            }
         }
      else if(op == 1)
         {
         if(ptrs.empty())
            return;

         size_t which_ptr = idx % ptrs.size();

         auto itr = ptrs.begin();

         while(which_ptr-- > 0)
            {
            ++itr;
            }

         //printf("free %p %d\n", itr->first, itr->second);
         FUZZER_ASSERT_TRUE(pool.deallocate(itr->first, itr->second));
         ptrs.erase(itr);
         }
      }
   }