#ifndef SIMDJSON_FUZZUTILS_H #define SIMDJSON_FUZZUTILS_H #include #include #include #include //memcpy // view data as a byte pointer template inline const std::uint8_t* as_bytes(const T* data) { return static_cast(static_cast(data)); } // view data as a char pointer template inline const char* as_chars(const T* data) { return static_cast(static_cast(data)); } // Splits the input into strings, using a four byte separator which is human // readable. Makes for nicer debugging of fuzz data. // See https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#magic-separator // for background. Note: don't use memmem, it is not standard C++. inline std::vector split(const char* Data, size_t Size) { std::vector ret; using namespace std::literals; constexpr auto sep="\n~~\n"sv; std::string_view all(Data,Size); auto pos=all.find(sep); while(pos!=std::string_view::npos) { ret.push_back(all.substr(0,pos)); all=all.substr(pos+sep.size()); pos=all.find(sep); } ret.push_back(all); return ret; } // Generic helper to split fuzz data into usable parts, like ints etc. // Note that it does not throw, instead it sets the data pointer to null // if the input is exhausted. struct FuzzData { // data may not be null, even if size is zero. FuzzData(const uint8_t* data, size_t size) : Data(data),Size(size){} ///range is inclusive template int getInt() { static_assert (Min(get()%urange); if(range<65536) return Min+static_cast(get()%urange); return Min+static_cast(get()%urange); } template T get() { const auto Nbytes=sizeof(T); T ret{}; if(Size std::string_view get_stringview() { static_assert (Min>=0,"Min must be positive"); const int len=getInt(); const unsigned int ulen=static_cast(len); if(ulen splitIntoStrings() { std::vector ret; if(Size>0) { ret=split(chardata(),Size); // all data consumed. Data+=Size; Size=0; } return ret; } //are we good? explicit operator bool() const { return Data!=nullptr;} //we are a URBG // https://en.cppreference.com/w/cpp/named_req/UniformRandomBitGenerator //The type G satisfies UniformRandomBitGenerator if Given // T, the type named by G::result_type // g, a value of type G // // The following expressions must be valid and have their specified effects // Expression Return type Requirements // G::result_type T T is an unsigned integer type using result_type=uint8_t; // G::min() T Returns the smallest value that G's operator() may return. The value is strictly less than G::max(). The function must be constexpr. static constexpr result_type min() {return 0;} // G::max() T Returns the largest value that G's operator() may return. The value is strictly greater than G::min(). The function must be constexpr. static constexpr result_type max() {return 255;} // g() T Returns a value in the closed interval [G::min(), G::max()]. Has amortized constant complexity. result_type operator()() { if(Size==0) { // return something varying, otherwise uniform_int_distribution may get // stuck return failcount++; } const result_type ret=Data[0]; Data++; Size--; return ret; } // returns a pointer to data as const char* to avoid those cstyle casts const char* chardata() const {return static_cast(static_cast(Data));} // members const uint8_t* Data; size_t Size; uint8_t failcount=0; }; #endif // SIMDJSON_FUZZUTILS_H