aboutsummaryrefslogtreecommitdiffstats
path: root/src/fuzzer
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-12-29 12:26:31 -0500
committerJack Lloyd <[email protected]>2018-12-29 12:26:31 -0500
commit8eeff9183e936384dca45e0923ac6f48e260eefd (patch)
tree93715de15cf970d988df0f925d82d645aec48bb3 /src/fuzzer
parentc3ed8aaf749345ce22e7407882be54f20f4a9640 (diff)
Add a fuzzer for Memory_Pool
Basically, test that it works. Accepts a sequence of alloc+free operations and verify that each pointer returned does not overlap with any other outstanding allocation, that the memory returned is zeroed, and that alignment is respected. Intended for testing #1800 but no reason not to land this first.
Diffstat (limited to 'src/fuzzer')
-rw-r--r--src/fuzzer/mem_pool.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/fuzzer/mem_pool.cpp b/src/fuzzer/mem_pool.cpp
new file mode 100644
index 000000000..40706bae1
--- /dev/null
+++ b/src/fuzzer/mem_pool.cpp
@@ -0,0 +1,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);
+ }
+ }
+ }