fuzz_test.cpp 5.6 KB

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