From 7975c0c3cbe19a7159336ad8fcb170fa6259b1cb Mon Sep 17 00:00:00 2001 From: Paul Dreik Date: Sun, 9 Jun 2019 20:06:02 +0200 Subject: [PATCH] apply lessons learned from chrono fuzzer on sprintf --- test/fuzzing/sprintf.cpp | 57 +++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/test/fuzzing/sprintf.cpp b/test/fuzzing/sprintf.cpp index cfce044cc298..1acced4f0619 100644 --- a/test/fuzzing/sprintf.cpp +++ b/test/fuzzing/sprintf.cpp @@ -9,11 +9,15 @@ #include #include +constexpr auto Nmax = std::max(sizeof(long double), sizeof(std::intmax_t)); + template 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{}; @@ -22,8 +26,8 @@ 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::value) { @@ -31,14 +35,18 @@ void doit(const uint8_t* Data, std::size_t Size) { } 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 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 @@ -51,21 +59,40 @@ template 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;