diff options
Diffstat (limited to '')
-rw-r--r-- | comm/third_party/botan/src/fuzzer/mem_pool.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/fuzzer/mem_pool.cpp b/comm/third_party/botan/src/fuzzer/mem_pool.cpp new file mode 100644 index 0000000000..7227462887 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/mem_pool.cpp @@ -0,0 +1,193 @@ +/* +* (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> + +#include <stdlib.h> + +namespace { + +size_t compute_expected_alignment(size_t plen) + { + if(Botan::is_power_of_2(plen)) + { + return plen; + } + else + { + return 8; + } + } + +struct RawPage + { + public: + RawPage(void* p) : m_p(p) {} + ~RawPage() { std::free(m_p); } + + RawPage(const RawPage& other) = default; + RawPage& operator=(const RawPage& other) = default; + + RawPage(RawPage&& other) : m_p(nullptr) + { + std::swap(m_p, other.m_p); + } + + RawPage& operator=(RawPage&& other) + { + if(this != &other) + { + std::swap(m_p, other.m_p); + } + return (*this); + } + + void* ptr() const { return m_p; } + private: + void* m_p; + }; + +std::vector<RawPage> allocate_raw_pages(size_t count, size_t page_size) + { + std::vector<RawPage> pages; + pages.reserve(count); + + for(size_t i = 0; i != count; ++i) + { + void* ptr = nullptr; + + int rc = ::posix_memalign(&ptr, page_size, page_size); + FUZZER_ASSERT_EQUAL(rc, 0); + + if(ptr) + { + pages.push_back(RawPage(ptr)); + } + } + + return pages; + } + +} + +void fuzz(const uint8_t in[], size_t in_len) + { + const size_t page_count = 4; + const size_t page_size = 4096; + + // static to avoid repeated allocations + static std::vector<RawPage> raw_mem = allocate_raw_pages(page_count, page_size); + + std::vector<void*> mem_pages; + mem_pages.reserve(raw_mem.size()); + for(size_t i = 0; i != raw_mem.size(); ++i) + mem_pages.push_back(raw_mem[i].ptr()); + + Botan::Memory_Pool pool(mem_pages, 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); + const size_t alignment = reinterpret_cast<uintptr_t>(p) % expected_alignment; + if(alignment != 0) + { + FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer " << static_cast<void*>(p) << " for len " << plen + << " expected " << expected_alignment << " got " << alignment); + } + + //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 " << static_cast<void*>(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 " << static_cast<void*>(ptr_before.first) << "/" << ptr_before.second << + " overlaps with new " << static_cast<void*>(p)); + } + } + + auto after = std::next(itr); + + if(after != ptrs.end()) + { + if(p + plen > after->first) + { + FUZZER_WRITE_AND_CRASH("New " << static_cast<void*>(p) << "/" << plen + << " overlaps following " << static_cast<void*>(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); + } + } + } |