diff options
author | Jack Lloyd <[email protected]> | 2018-12-29 12:26:31 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-12-29 12:26:31 -0500 |
commit | 8eeff9183e936384dca45e0923ac6f48e260eefd (patch) | |
tree | 93715de15cf970d988df0f925d82d645aec48bb3 /src/fuzzer | |
parent | c3ed8aaf749345ce22e7407882be54f20f4a9640 (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.cpp | 114 |
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); + } + } + } |