Skip to content

Commit

Permalink
apply lessons learned from chrono fuzzer on sprintf
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldreik committed Jun 9, 2019
1 parent 972124c commit 7975c0c
Showing 1 changed file with 42 additions and 15 deletions.
57 changes: 42 additions & 15 deletions test/fuzzing/sprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
#include <type_traits>
#include <vector>

constexpr auto Nmax = std::max(sizeof(long double), sizeof(std::intmax_t));

template <typename Item1, typename Item2>
void doit(const uint8_t* Data, std::size_t Size) {
const auto N1 = sizeof(Item1);
const auto N2 = sizeof(Item2);
if (Size <= N1 + N2) {
static_assert(N1 <= Nmax, "size1 exceeded");
static_assert(N2 <= Nmax, "size2 exceeded");
if (Size <= Nmax + Nmax) {
return;
}
Item1 item1{};
Expand All @@ -22,23 +26,27 @@ void doit(const uint8_t* Data, std::size_t Size) {
} else {
std::memcpy(&item1, Data, N1);
}
Data += N1;
Size -= N1;
Data += Nmax;
Size -= Nmax;

Item2 item2{};
if /*constexpr*/ (std::is_same<Item2, bool>::value) {
item2 = !!Data[0];
} else {
std::memcpy(&item2, Data, N2);
}
Data += N2;
Size -= N2;
Data += Nmax;
Size -= Nmax;

auto fmtstring = fmt::string_view((const char*)Data, Size);

// allocates as tight as possible, making it easier to catch buffer overruns.
// also, make it null terminated.
std::vector<char> buf(Size + 1);
std::memcpy(buf.data(), Data, Size);
std::string message = fmt::sprintf(buf.data(), item1, item2);
#define ALLOCATE_RESULT_IN_STRING 0
#if ALLOCATE_RESULT_IN_STRING
std::string message = fmt::format(fmtstring, item1, item2);
#else
fmt::memory_buffer message;
fmt::format_to(message, fmtstring, item1, item2);
#endif
}

// for dynamic dispatching to an explicit instantiation
Expand All @@ -51,21 +59,40 @@ template <typename Callback> void invoke(int index, Callback callback) {
callback(char{});
break;
case 2:
callback(short{});
using sc = signed char;
callback(sc{});
break;
case 3:
callback(int{});
using uc = unsigned char;
callback(uc{});
break;
case 4:
callback(long{});
callback(short{});
break;
case 5:
callback(float{});
using us = unsigned short;
callback(us{});
break;
case 6:
callback(double{});
callback(int{});
break;
case 7:
callback(unsigned{});
break;
case 8:
callback(long{});
break;
case 9:
using ul = unsigned long;
callback(ul{});
break;
case 10:
callback(float{});
break;
case 11:
callback(double{});
break;
case 12:
using LD = long double;
callback(LD{});
break;
Expand Down

0 comments on commit 7975c0c

Please sign in to comment.