/* * For fuzzing all of the implementations (haswell/fallback/westmere), * finding any difference between the output of each which would * indicate inconsistency. Also, it gets the non-default backend * some fuzzing love. * * Copyright Paul Dreik 20200909 for the simdjson project. */ #include "simdjson.h" #include #include #include #include #include #include "supported_implementations.h" // store each implementation along with it's intermediate results, // which would make things easier to debug in case this fuzzer ever // catches anything struct Impl { explicit Impl(const simdjson::implementation* im=nullptr) : impl(im),parser(),element(),error(),output(){} //silence -Weffc++ Impl(const Impl&)=delete; Impl& operator=(const Impl&)=delete; const simdjson::implementation* impl; simdjson::dom::parser parser; simdjson::dom::element element; simdjson::error_code error; std::string output; }; template void showErrorAndAbort(Iterator first, Iterator last) { auto it=first; while(it!=last) { std::cerr<<"Implementation: "<impl->name()<<"\tError:"<error<<'\n'; it++; } std::cerr.flush(); std::abort(); } template void showOutputAndAbort(Iterator first, Iterator last) { for(auto it=first;it!=last;++it) { std::cerr<<"Implementation: "<impl->name()<<"\tOutput: "<output<<'\n'; } // show the pairwise results for(auto it1=first; it1!=last; ++it1) { for(auto it2=it1; it2!=last; ++it2) { if(it1!=it2) { const bool matches=(it1->output==it2->output); std::cerr<<"Implementation "<impl->name()<<" and "<impl->name()<<(matches?" match.":" do NOT match.")<<'\n'; } } } std::cerr.flush(); std::abort(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { // since this check is expensive, only do it once static const auto supported_implementations=get_runtime_supported_implementations(); // make this dynamic, so it works regardless of how it was compiled // or what hardware it runs on constexpr std::size_t Nimplementations_max=3; const std::size_t Nimplementations = supported_implementations.size(); if(Nimplementations>Nimplementations_max) { //there is another backend added, please bump Nimplementations_max! std::abort(); } // get pointers to the backend implementation std::array implementations; { std::size_t i=0; for(auto& e: supported_implementations) { implementations[i++].impl=e; } } // let each implementation parse and store the result std::size_t nerrors=0; for(std::size_t i=0; i