libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

fuzz_test.cpp (5702B)


      1 // -*- C++ -*-
      2 //===------------------------- fuzz_test.cpp ------------------------------===//
      3 //
      4 //                     The LLVM Compiler Infrastructure
      5 //
      6 // This file is dual licensed under the MIT and the University of Illinois Open
      7 // Source Licenses. See LICENSE.TXT for details.
      8 //
      9 //===----------------------------------------------------------------------===//
     10 
     11 //  A simple program for running regressions on the fuzzing routines.
     12 //  This code is not part of any shipping product.
     13 //
     14 //  To build:
     15 //      clang++ -std=c++11 fuzz_test.cpp fuzzing.cpp
     16 //
     17 //  To use:
     18 //      fuzz_test -r partial_sort [-v] files...
     19 //
     20 //  Each file should contain a test case.
     21 
     22 //  TODO: should add some memory tracking, too.
     23 
     24 
     25 #include <iostream>
     26 #include <fstream>
     27 #include <iterator>
     28 #include <vector>
     29 #include <map>
     30 #include <chrono>
     31 
     32 #include "fuzzing.h"
     33 
     34 //  ==== Count memory allocations ====
     35 
     36 struct MemoryCounters {
     37     size_t totalAllocationCount;
     38     size_t netAllocationCount;
     39     size_t totalBytesAllocated;
     40     };
     41 
     42 MemoryCounters gMemoryCounters;
     43 
     44 void ZeroMemoryCounters() {
     45     gMemoryCounters.totalAllocationCount = 0;
     46     gMemoryCounters.netAllocationCount = 0;
     47     gMemoryCounters.totalBytesAllocated = 0;
     48 }
     49 
     50 void* operator new(std::size_t size)
     51 {
     52     if (size == 0) size = 1;
     53     void *p = ::malloc(size);
     54     if (p == NULL)
     55         throw std::bad_alloc();
     56     gMemoryCounters.totalAllocationCount += 1;
     57     gMemoryCounters.netAllocationCount  += 1;
     58     gMemoryCounters.totalBytesAllocated += size;
     59     return p;
     60 }
     61 
     62 void* operator new(std::size_t size, const std::nothrow_t&) noexcept
     63 {
     64     try { return operator new(size); }
     65     catch (const std::bad_alloc &) {}
     66     return nullptr;
     67 }
     68 
     69 void* operator new[](std::size_t size)
     70 {
     71     return ::operator new(size);
     72 }
     73 
     74 void* operator new[](std::size_t size, const std::nothrow_t&) noexcept
     75 {
     76     try { return operator new(size); }
     77     catch (const std::bad_alloc &) {}
     78     return nullptr;
     79 }
     80 
     81 void  operator delete(void* ptr) noexcept
     82 {
     83     if (ptr)
     84         ::free(ptr);
     85     gMemoryCounters.netAllocationCount -= 1;
     86 }
     87 
     88 void  operator delete(void* ptr, const std::nothrow_t&) noexcept
     89 {
     90     ::operator delete(ptr);
     91 }
     92 
     93 void  operator delete[](void* ptr) noexcept
     94 {
     95     ::operator delete(ptr);
     96 }
     97 
     98 void  operator delete[](void* ptr, const std::nothrow_t&) noexcept
     99 {
    100     ::operator delete(ptr);
    101 }
    102 
    103 //  ==== End count memory allocations ====
    104 
    105 
    106 typedef int (*FuzzProc) (const uint8_t *data, size_t size);
    107 
    108 const std::map<std::string, FuzzProc> procs = {
    109     {"sort",                fuzzing::sort},
    110     {"stable_sort",         fuzzing::stable_sort},
    111     {"partition",           fuzzing::partition},
    112     {"partition_copy",      fuzzing::partition_copy},
    113     {"stable_partition",    fuzzing::stable_partition},
    114     {"unique",              fuzzing::unique},
    115     {"unique_copy",         fuzzing::unique_copy},
    116     {"nth_element",         fuzzing::nth_element},
    117     {"partial_sort",        fuzzing::partial_sort},
    118     {"partial_sort_copy",   fuzzing::partial_sort_copy},
    119     {"make_heap",           fuzzing::make_heap},
    120     {"push_heap",           fuzzing::push_heap},
    121     {"pop_heap",            fuzzing::pop_heap},
    122     {"regex_ECMAScript",    fuzzing::regex_ECMAScript},
    123     {"regex_POSIX",         fuzzing::regex_POSIX},
    124     {"regex_extended",      fuzzing::regex_extended},
    125     {"regex_awk",           fuzzing::regex_awk},
    126     {"regex_grep",          fuzzing::regex_grep},
    127     {"regex_egrep",         fuzzing::regex_egrep},
    128     {"search",              fuzzing::search}
    129 };
    130 
    131 
    132 
    133 bool verbose = false;
    134 
    135 void test_one(const char *filename, FuzzProc fp)
    136 {
    137     std::vector<uint8_t> v;
    138     std::ifstream f (filename, std::ios::binary);
    139     if (!f.is_open())
    140         std::cerr << "## Can't open '" << filename << "'" << std::endl;
    141     else
    142     {
    143         typedef std::istream_iterator<uint8_t> Iter;
    144         std::copy(Iter(f), Iter(), std::back_inserter(v));
    145         if (verbose)
    146             std::cout << "File '" << filename << "' contains " << v.size() << " entries" << std::endl;
    147         ZeroMemoryCounters();
    148         const auto start_time = std::chrono::high_resolution_clock::now();
    149         int ret = fp (v.data(), v.size());
    150         const auto finish_time = std::chrono::high_resolution_clock::now();
    151         MemoryCounters mc = gMemoryCounters;
    152         if (ret != 0)
    153             std::cerr << "## Failure code: " << ret << std::endl;
    154         if (verbose)
    155         {
    156             std::cout << "Execution time: "
    157                 << std::chrono::duration_cast<std::chrono::milliseconds>(finish_time - start_time).count()
    158                 << " milliseconds" << std::endl;
    159             std::cout << "Memory: " 
    160                       << mc.totalBytesAllocated  << " bytes allocated ("
    161                       << mc.totalAllocationCount << " allocations); "
    162                       << mc.netAllocationCount   << " allocations remain" << std::endl;
    163         }
    164     }
    165 }
    166 
    167 void usage (const char *name)
    168 {
    169     std::cout << "Usage: " << name << " -r proc [-v] files..." << std::endl;
    170     std::cout << "Supported routines:" << std::endl;
    171     for (const auto &p : procs)
    172         std::cout << "    " << p.first << std::endl;
    173     std::cout << std::endl;
    174 }
    175 
    176 // Poor man's command-line options
    177 const std::string dashR("-r");
    178 const std::string dashV("-v");
    179 
    180 int main(int argc, char *argv[])
    181 {
    182     if (argc < 4 || dashR != argv[1] || procs.find(argv[2]) == procs.end())
    183         usage(argv[0]);
    184     else {
    185         FuzzProc fp = procs.find(argv[2])->second;
    186         int firstFile = 3;
    187         if (dashV == argv[firstFile])
    188         {
    189             verbose = true;
    190             ++firstFile;
    191         }
    192         for (int i = firstFile; i < argc; ++i)
    193             test_one(argv[i], fp);
    194         }
    195 }