mirror of
				https://github.com/fmtlib/fmt.git
				synced 2025-11-04 08:01:40 +01:00 
			
		
		
		
	
		
			
	
	
		
			117 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			117 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								// Copyright (c) 2019, Paul Dreik
							 | 
						||
| 
								 | 
							
								// License: see LICENSE.rst in the fmt root directory
							 | 
						||
| 
								 | 
							
								#include <fmt/format.h>
							 | 
						||
| 
								 | 
							
								#include <fmt/printf.h>
							 | 
						||
| 
								 | 
							
								#include <cstdint>
							 | 
						||
| 
								 | 
							
								#include <stdexcept>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "fuzzer_common.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using fmt_fuzzer::Nfixed;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <typename Item1, typename Item2>
							 | 
						||
| 
								 | 
							
								void invoke_fmt(const uint8_t* Data, std::size_t Size) {
							 | 
						||
| 
								 | 
							
								  constexpr auto N1 = sizeof(Item1);
							 | 
						||
| 
								 | 
							
								  constexpr auto N2 = sizeof(Item2);
							 | 
						||
| 
								 | 
							
								  static_assert(N1 <= Nfixed, "size1 exceeded");
							 | 
						||
| 
								 | 
							
								  static_assert(N2 <= Nfixed, "size2 exceeded");
							 | 
						||
| 
								 | 
							
								  if (Size <= Nfixed + Nfixed) {
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  Item1 item1 = fmt_fuzzer::assignFromBuf<Item1>(Data);
							 | 
						||
| 
								 | 
							
								  Data += Nfixed;
							 | 
						||
| 
								 | 
							
								  Size -= Nfixed;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Item2 item2 = fmt_fuzzer::assignFromBuf<Item2>(Data);
							 | 
						||
| 
								 | 
							
								  Data += Nfixed;
							 | 
						||
| 
								 | 
							
								  Size -= Nfixed;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto fmtstring = fmt::string_view(fmt_fuzzer::as_chars(Data), Size);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if FMT_FUZZ_FORMAT_TO_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
							 | 
						||
| 
								 | 
							
								template <typename Callback> void invoke(int index, Callback callback) {
							 | 
						||
| 
								 | 
							
								  switch (index) {
							 | 
						||
| 
								 | 
							
								  case 0:
							 | 
						||
| 
								 | 
							
								    callback(bool{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  case 1:
							 | 
						||
| 
								 | 
							
								    callback(char{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  case 2:
							 | 
						||
| 
								 | 
							
								    using sc = signed char;
							 | 
						||
| 
								 | 
							
								    callback(sc{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  case 3:
							 | 
						||
| 
								 | 
							
								    using uc = unsigned char;
							 | 
						||
| 
								 | 
							
								    callback(uc{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  case 4:
							 | 
						||
| 
								 | 
							
								    callback(short{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  case 5:
							 | 
						||
| 
								 | 
							
								    using us = unsigned short;
							 | 
						||
| 
								 | 
							
								    callback(us{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  case 6:
							 | 
						||
| 
								 | 
							
								    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;
							 | 
						||
| 
								 | 
							
								  case 13:
							 | 
						||
| 
								 | 
							
								    using ptr = void*;
							 | 
						||
| 
								 | 
							
								    callback(ptr{});
							 | 
						||
| 
								 | 
							
								    break;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, std::size_t Size) {
							 | 
						||
| 
								 | 
							
								  if (Size <= 3) {
							 | 
						||
| 
								 | 
							
								    return 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // switch types depending on the first byte of the input
							 | 
						||
| 
								 | 
							
								  const auto first = Data[0] & 0x0F;
							 | 
						||
| 
								 | 
							
								  const auto second = (Data[0] & 0xF0) >> 4;
							 | 
						||
| 
								 | 
							
								  Data++;
							 | 
						||
| 
								 | 
							
								  Size--;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto outer = [=](auto param1) {
							 | 
						||
| 
								 | 
							
								    auto inner = [=](auto param2) {
							 | 
						||
| 
								 | 
							
								      invoke_fmt<decltype(param1), decltype(param2)>(Data, Size);
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								    invoke(second, inner);
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    invoke(first, outer);
							 | 
						||
| 
								 | 
							
								  } catch (std::exception& /*e*/) {
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 |