// Copyright (c) 2019, Paul Dreik // License: see LICENSE.rst in the fmt root directory #include #include #include #include #include #include #include "fuzzer_common.h" using fmt_fuzzer::Nfixed; template void invoke_fmt(const uint8_t* Data, size_t Size) { constexpr auto N = sizeof(Item); static_assert(N <= Nfixed, "Nfixed is too small"); if (Size <= Nfixed) { return; } const Item item = fmt_fuzzer::assignFromBuf(Data); Data += Nfixed; Size -= Nfixed; #if FMT_FUZZ_SEPARATE_ALLOCATION // allocates as tight as possible, making it easier to catch buffer overruns. std::vector fmtstringbuffer(Size); std::memcpy(fmtstringbuffer.data(), Data, Size); auto fmtstring = fmt::string_view(fmtstringbuffer.data(), Size); #else auto fmtstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size); #endif #if FMT_FUZZ_FORMAT_TO_STRING std::string message = fmt::format(fmtstring, item); #else fmt::memory_buffer message; fmt::format_to(message, fmtstring, item); #endif } void invoke_fmt_time(const uint8_t* Data, size_t Size) { using Item = std::time_t; constexpr auto N = sizeof(Item); static_assert(N <= Nfixed, "Nfixed too small"); if (Size <= Nfixed) { return; } const Item item = fmt_fuzzer::assignFromBuf(Data); Data += Nfixed; Size -= Nfixed; #if FMT_FUZZ_SEPARATE_ALLOCATION // allocates as tight as possible, making it easier to catch buffer overruns. std::vector fmtstringbuffer(Size); std::memcpy(fmtstringbuffer.data(), Data, Size); auto fmtstring = fmt::string_view(fmtstringbuffer.data(), Size); #else auto fmtstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size); #endif auto* b = std::localtime(&item); if (b) { #if FMT_FUZZ_FORMAT_TO_STRING std::string message = fmt::format(fmtstring, *b); #else fmt::memory_buffer message; fmt::format_to(message, fmtstring, *b); #endif } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { if (Size <= 3) { return 0; } const auto first = Data[0]; Data++; Size--; try { switch (first) { case 0: invoke_fmt(Data, Size); break; case 1: invoke_fmt(Data, Size); break; case 2: invoke_fmt(Data, Size); break; case 3: invoke_fmt(Data, Size); break; case 4: invoke_fmt(Data, Size); break; case 5: invoke_fmt(Data, Size); break; case 6: invoke_fmt(Data, Size); break; case 7: invoke_fmt(Data, Size); break; case 8: invoke_fmt(Data, Size); break; case 9: invoke_fmt(Data, Size); break; case 10: invoke_fmt(Data, Size); break; case 11: invoke_fmt(Data, Size); break; case 12: invoke_fmt(Data, Size); break; case 13: invoke_fmt_time(Data, Size); break; default: break; } } catch (std::exception& /*e*/) { } return 0; }