#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "flatbuffers/code_generator.h" #include "flatbuffers/idl.h" // For Parser and generation functions #include "idl_gen_cpp.h" // For C++ generator #include "test_init.h" static constexpr size_t kMinInputLength = 1; static constexpr size_t kMaxInputLength = 16384; static constexpr uint8_t flags_strict_json = 0x80; static constexpr uint8_t flags_skip_unexpected_fields_in_json = 0x40; static constexpr uint8_t flags_allow_non_utf8 = 0x20; // Utility for test run. OneTimeTestInit OneTimeTestInit::one_time_init_; static const char* g_program_name = nullptr; static void Warn(const flatbuffers::FlatCompiler* flatc, const std::string& warn, bool show_exe_name) { (void)flatc; if (show_exe_name) { printf("%s: ", g_program_name); } fprintf(stderr, "\nwarning:\n %s\n\n", warn.c_str()); } static void Error(const flatbuffers::FlatCompiler* flatc, const std::string& err, bool usage, bool show_exe_name) { if (show_exe_name) { printf("%s: ", g_program_name); } if (usage && flatc) { fprintf(stderr, "%s\n", flatc->GetShortUsageString(g_program_name).c_str()); } fprintf(stderr, "\nerror:\n %s\n\n", err.c_str()); exit(1); } namespace flatbuffers { void LogCompilerWarn(const std::string& warn) { Warn(static_cast(nullptr), warn, true); } void LogCompilerError(const std::string& err) { Error(static_cast(nullptr), err, false, true); } } // namespace flatbuffers extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Reserve one byte for Parser flags and one byte for repetition counter. if (size < 3) return 0; const uint8_t flags = data[0]; (void)data[1]; // reserved data += 2; size -= 2; // bypass const std::string original(reinterpret_cast(data), size); auto input = std::string(original.c_str()); // until '\0' if (input.size() < kMinInputLength || input.size() > kMaxInputLength) return 0; flatbuffers::IDLOptions opts; opts.strict_json = (flags & flags_strict_json); opts.skip_unexpected_fields_in_json = (flags & flags_skip_unexpected_fields_in_json); opts.allow_non_utf8 = (flags & flags_allow_non_utf8); flatbuffers::Parser parser(opts); // Guarantee 0-termination in the input. auto parse_input = input.c_str(); // Parse the input schema if (parser.Parse(parse_input)) { parser.Serialize(); const uint8_t* buf = parser.builder_.GetBufferPointer(); flatbuffers::Verifier verifier(buf, parser.builder_.GetSize()); TEST_EQ(true, reflection::VerifySchemaBuffer(verifier)); auto root = flatbuffers::GetRoot(buf); if (verifier.VerifyTableStart(buf) && root->VerifyTableStart(verifier)) { if (parser.root_struct_def_) { std::string json_output; flatbuffers::GenText(parser, parser.builder_.GetBufferPointer(), &json_output); } } std::string temp_filename = "fuzzer_generated"; const std::string flatbuffers_version(flatbuffers::FLATBUFFERS_VERSION()); std::vector> generators; generators.emplace_back(flatbuffers::NewBinaryCodeGenerator()); generators.emplace_back(flatbuffers::NewCppCodeGenerator()); generators.emplace_back(flatbuffers::NewCSharpCodeGenerator()); generators.emplace_back(flatbuffers::NewDartCodeGenerator()); generators.emplace_back(flatbuffers::NewFBSCodeGenerator()); generators.emplace_back(flatbuffers::NewGoCodeGenerator()); generators.emplace_back(flatbuffers::NewJavaCodeGenerator()); generators.emplace_back(flatbuffers::NewJsonSchemaCodeGenerator()); generators.emplace_back(flatbuffers::NewKotlinCodeGenerator()); generators.emplace_back(flatbuffers::NewKotlinKMPCodeGenerator()); generators.emplace_back(flatbuffers::NewLobsterCodeGenerator()); generators.emplace_back( flatbuffers::NewLuaBfbsGenerator(flatbuffers_version)); generators.emplace_back( flatbuffers::NewNimBfbsGenerator(flatbuffers_version)); generators.emplace_back(flatbuffers::NewPythonCodeGenerator()); generators.emplace_back(flatbuffers::NewPhpCodeGenerator()); generators.emplace_back(flatbuffers::NewRustCodeGenerator()); generators.emplace_back(flatbuffers::NewTextCodeGenerator()); generators.emplace_back(flatbuffers::NewSwiftCodeGenerator()); generators.emplace_back(flatbuffers::NewTsCodeGenerator()); for (auto& gen : generators) { auto p = gen.get(); std::string temp_path = "/tmp/"; auto status = p->GenerateCode(parser, temp_path, "fuzzer_generated"); if (status != flatbuffers::CodeGenerator::Status::OK) { TEST_OUTPUT_LINE("GenerateCode failed %d", status); } // test gRPC code generation auto grpc_status = p->GenerateGrpcCode(parser, temp_path, "fuzzer_generated"); if (grpc_status != flatbuffers::CodeGenerator::Status::OK) { TEST_OUTPUT_LINE("GenerateGrpcCode failed %d", grpc_status); } } } return 0; }