mirror of
				https://github.com/fmtlib/fmt.git
				synced 2025-10-31 22:21:41 +01:00 
			
		
		
		
	
		
			
	
	
		
			153 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			153 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | // Copyright (c) 2019, Paul Dreik
 | ||
|  | // License: see LICENSE.rst in the fmt root directory
 | ||
|  | 
 | ||
|  | #include <fmt/chrono.h>
 | ||
|  | #include <cstdint>
 | ||
|  | #include <limits>
 | ||
|  | #include <stdexcept>
 | ||
|  | #include <type_traits>
 | ||
|  | #include <vector>
 | ||
|  | #include "fuzzer_common.h"
 | ||
|  | 
 | ||
|  | template <typename Item, typename Ratio> | ||
|  | void invoke_inner(fmt::string_view formatstring, const Item item) { | ||
|  |   const std::chrono::duration<Item, Ratio> value(item); | ||
|  |   try { | ||
|  | #if FMT_FUZZ_FORMAT_TO_STRING
 | ||
|  |     std::string message = fmt::format(formatstring, value); | ||
|  | #else
 | ||
|  |     fmt::memory_buffer buf; | ||
|  |     fmt::format_to(buf, formatstring, value); | ||
|  | #endif
 | ||
|  |   } catch (std::exception& /*e*/) { | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | // Item is the underlying type for duration (int, long etc)
 | ||
|  | template <typename Item> | ||
|  | void invoke_outer(const uint8_t* Data, std::size_t Size, const int scaling) { | ||
|  |   // always use a fixed location of the data
 | ||
|  |   using fmt_fuzzer::Nfixed; | ||
|  | 
 | ||
|  |   constexpr auto N = sizeof(Item); | ||
|  |   static_assert(N <= Nfixed, "fixed size is too small"); | ||
|  |   if (Size <= Nfixed + 1) { | ||
|  |     return; | ||
|  |   } | ||
|  | 
 | ||
|  |   const Item item = fmt_fuzzer::assignFromBuf<Item>(Data); | ||
|  | 
 | ||
|  |   // fast forward
 | ||
|  |   Data += Nfixed; | ||
|  |   Size -= Nfixed; | ||
|  | 
 | ||
|  |   // Data is already allocated separately in libFuzzer so reading past
 | ||
|  |   // the end will most likely be detected anyway
 | ||
|  |   const auto formatstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size); | ||
|  | 
 | ||
|  |   // doit_impl<Item,std::yocto>(buf.data(),item);
 | ||
|  |   // doit_impl<Item,std::zepto>(buf.data(),item);
 | ||
|  |   switch (scaling) { | ||
|  |   case 1: | ||
|  |     invoke_inner<Item, std::atto>(formatstring, item); | ||
|  |     break; | ||
|  |   case 2: | ||
|  |     invoke_inner<Item, std::femto>(formatstring, item); | ||
|  |     break; | ||
|  |   case 3: | ||
|  |     invoke_inner<Item, std::pico>(formatstring, item); | ||
|  |     break; | ||
|  |   case 4: | ||
|  |     invoke_inner<Item, std::nano>(formatstring, item); | ||
|  |     break; | ||
|  |   case 5: | ||
|  |     invoke_inner<Item, std::micro>(formatstring, item); | ||
|  |     break; | ||
|  |   case 6: | ||
|  |     invoke_inner<Item, std::milli>(formatstring, item); | ||
|  |     break; | ||
|  |   case 7: | ||
|  |     invoke_inner<Item, std::centi>(formatstring, item); | ||
|  |     break; | ||
|  |   case 8: | ||
|  |     invoke_inner<Item, std::deci>(formatstring, item); | ||
|  |     break; | ||
|  |   case 9: | ||
|  |     invoke_inner<Item, std::deca>(formatstring, item); | ||
|  |     break; | ||
|  |   case 10: | ||
|  |     invoke_inner<Item, std::kilo>(formatstring, item); | ||
|  |     break; | ||
|  |   case 11: | ||
|  |     invoke_inner<Item, std::mega>(formatstring, item); | ||
|  |     break; | ||
|  |   case 12: | ||
|  |     invoke_inner<Item, std::giga>(formatstring, item); | ||
|  |     break; | ||
|  |   case 13: | ||
|  |     invoke_inner<Item, std::tera>(formatstring, item); | ||
|  |     break; | ||
|  |   case 14: | ||
|  |     invoke_inner<Item, std::peta>(formatstring, item); | ||
|  |     break; | ||
|  |   case 15: | ||
|  |     invoke_inner<Item, std::exa>(formatstring, item); | ||
|  |   } | ||
|  |   // doit_impl<Item,std::zeta>(buf.data(),item);
 | ||
|  |   // doit_impl<Item,std::yotta>(buf.data(),item);
 | ||
|  | } | ||
|  | 
 | ||
|  | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) { | ||
|  |   if (Size <= 4) { | ||
|  |     return 0; | ||
|  |   } | ||
|  | 
 | ||
|  |   const auto representation = Data[0]; | ||
|  |   const auto scaling = Data[1]; | ||
|  |   Data += 2; | ||
|  |   Size -= 2; | ||
|  | 
 | ||
|  |   switch (representation) { | ||
|  |   case 1: | ||
|  |     invoke_outer<char>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 2: | ||
|  |     invoke_outer<unsigned char>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 3: | ||
|  |     invoke_outer<signed char>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 4: | ||
|  |     invoke_outer<short>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 5: | ||
|  |     invoke_outer<unsigned short>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 6: | ||
|  |     invoke_outer<int>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 7: | ||
|  |     invoke_outer<unsigned int>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 8: | ||
|  |     invoke_outer<long>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 9: | ||
|  |     invoke_outer<unsigned long>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 10: | ||
|  |     invoke_outer<float>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 11: | ||
|  |     invoke_outer<double>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   case 12: | ||
|  |     invoke_outer<long double>(Data, Size, scaling); | ||
|  |     break; | ||
|  |   default: | ||
|  |     break; | ||
|  |   } | ||
|  | 
 | ||
|  |   return 0; | ||
|  | } |