aboutsummaryrefslogtreecommitdiffstats
path: root/src/fuzzer/mem_pool.cpp
blob: d6305997d0adf8f9bdf17e857f1ad038618cabdb (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* (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 <botan/internal/bit_ops.h>
#include <vector>
#include <map>
#include <utility>

namespace {

size_t compute_expected_alignment(size_t plen)
   {
   if(Botan::is_power_of_2(plen))
      {
      return plen;
      }
   else
      {
      return 8;
      }
   }

}

void fuzz(const uint8_t in[], size_t in_len)
   {
   const size_t page_size = 4096;

   static std::vector<void*> raw_mem{malloc(page_size),
                                     malloc(page_size),
                                     malloc(page_size),
                                     malloc(page_size)};


   Botan::Memory_Pool pool(raw_mem, page_size);
   std::map<uint8_t*, size_t> ptrs;

   while(in_len > 0)
      {
      const uint8_t op = in[0] % 2;
      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;
         }

      //printf("%d %d\n", op, idx);

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

         if(p)
            {
            const size_t expected_alignment = compute_expected_alignment(plen);
            if(reinterpret_cast<uintptr_t>(p) % expected_alignment != 0)
               {
               FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer " << 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);
         }
      }
   }