named-arg.cc 2.2 KB

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