two-args.cc 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Copyright (c) 2019, Paul Dreik
  2. // For the license information refer to format.h.
  3. #include <fmt/format.h>
  4. #include <cstdint>
  5. #include <exception>
  6. #include <string>
  7. #include "fuzzer-common.h"
  8. template <typename Item1, typename Item2>
  9. void invoke_fmt(const uint8_t* data, size_t size) {
  10. static_assert(sizeof(Item1) <= fixed_size, "size1 exceeded");
  11. static_assert(sizeof(Item2) <= fixed_size, "size2 exceeded");
  12. if (size <= fixed_size + fixed_size) return;
  13. const Item1 item1 = assign_from_buf<Item1>(data);
  14. data += fixed_size;
  15. size -= fixed_size;
  16. const Item2 item2 = assign_from_buf<Item2>(data);
  17. data += fixed_size;
  18. size -= fixed_size;
  19. auto format_str = fmt::string_view(as_chars(data), size);
  20. #if FMT_FUZZ_FORMAT_TO_STRING
  21. std::string message = fmt::format(format_str, item1, item2);
  22. #else
  23. auto buf = fmt::memory_buffer();
  24. fmt::format_to(std::back_inserter(buf), format_str, item1, item2);
  25. #endif
  26. }
  27. // For dynamic dispatching to an explicit instantiation.
  28. template <typename Callback> void invoke(int index, Callback callback) {
  29. switch (index) {
  30. case 0:
  31. callback(bool());
  32. break;
  33. case 1:
  34. callback(char());
  35. break;
  36. case 2:
  37. using sc = signed char;
  38. callback(sc());
  39. break;
  40. case 3:
  41. using uc = unsigned char;
  42. callback(uc());
  43. break;
  44. case 4:
  45. callback(short());
  46. break;
  47. case 5:
  48. using us = unsigned short;
  49. callback(us());
  50. break;
  51. case 6:
  52. callback(int());
  53. break;
  54. case 7:
  55. callback(unsigned());
  56. break;
  57. case 8:
  58. callback(long());
  59. break;
  60. case 9:
  61. using ul = unsigned long;
  62. callback(ul());
  63. break;
  64. case 10:
  65. callback(float());
  66. break;
  67. case 11:
  68. callback(double());
  69. break;
  70. case 12:
  71. using LD = long double;
  72. callback(LD());
  73. break;
  74. case 13:
  75. using ptr = void*;
  76. callback(ptr());
  77. break;
  78. }
  79. }
  80. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
  81. if (size <= 3) return 0;
  82. // Switch types depending on the first byte of the input.
  83. const auto type1 = data[0] & 0x0F;
  84. const auto type2 = (data[0] & 0xF0) >> 4;
  85. data++;
  86. size--;
  87. try {
  88. invoke(type1, [=](auto param1) {
  89. invoke(type2, [=](auto param2) {
  90. invoke_fmt<decltype(param1), decltype(param2)>(data, size);
  91. });
  92. });
  93. } catch (std::exception&) {
  94. }
  95. return 0;
  96. }