|
| 1 | +#include <stddef.h> |
| 2 | +#include <stdint.h> |
| 3 | +#include <string> |
| 4 | +#include "flatbuffers/idl.h" // For Parser and generation functions |
| 5 | +#include "test_init.h" |
| 6 | +#include <memory> |
| 7 | +#include <flatbuffers/flatc.h> |
| 8 | +#include "idl_gen_cpp.h" // For C++ generator |
| 9 | +#include <idl_gen_csharp.h> |
| 10 | +#include <iostream> |
| 11 | +#include "flatbuffers/code_generator.h" |
| 12 | +#include <idl_gen_binary.h> |
| 13 | +#include <idl_gen_dart.h> |
| 14 | +#include <idl_gen_fbs.h> |
| 15 | +#include <idl_gen_go.h> |
| 16 | +#include <idl_gen_java.h> |
| 17 | +#include <idl_gen_json_schema.h> |
| 18 | +#include <idl_gen_kotlin.h> |
| 19 | +#include <idl_gen_kotlin.h> |
| 20 | +#include <idl_gen_lobster.h> |
| 21 | +#include <bfbs_gen_lua.h> |
| 22 | +#include <bfbs_gen_nim.h> |
| 23 | +#include <idl_gen_python.h> |
| 24 | +#include <idl_gen_php.h> |
| 25 | +#include <idl_gen_rust.h> |
| 26 | +#include <idl_gen_text.h> |
| 27 | +#include <idl_gen_swift.h> |
| 28 | +#include <idl_gen_ts.h> |
| 29 | + |
| 30 | +static constexpr size_t kMinInputLength = 1; |
| 31 | +static constexpr size_t kMaxInputLength = 16384; |
| 32 | + |
| 33 | +static constexpr uint8_t flags_strict_json = 0x80; |
| 34 | +static constexpr uint8_t flags_skip_unexpected_fields_in_json = 0x40; |
| 35 | +static constexpr uint8_t flags_allow_non_utf8 = 0x20; |
| 36 | + |
| 37 | +// Utility for test run. |
| 38 | +OneTimeTestInit OneTimeTestInit::one_time_init_; |
| 39 | + |
| 40 | +static const char* g_program_name = nullptr; |
| 41 | + |
| 42 | +static void Warn(const flatbuffers::FlatCompiler* flatc, |
| 43 | + const std::string& warn, bool show_exe_name) { |
| 44 | + (void)flatc; |
| 45 | + if (show_exe_name) { |
| 46 | + printf("%s: ", g_program_name); |
| 47 | + } |
| 48 | + fprintf(stderr, "\nwarning:\n %s\n\n", warn.c_str()); |
| 49 | +} |
| 50 | + |
| 51 | +static void Error(const flatbuffers::FlatCompiler* flatc, |
| 52 | + const std::string& err, bool usage, bool show_exe_name) { |
| 53 | + if (show_exe_name) { |
| 54 | + printf("%s: ", g_program_name); |
| 55 | + } |
| 56 | + if (usage && flatc) { |
| 57 | + fprintf(stderr, "%s\n", flatc->GetShortUsageString(g_program_name).c_str()); |
| 58 | + } |
| 59 | + fprintf(stderr, "\nerror:\n %s\n\n", err.c_str()); |
| 60 | + exit(1); |
| 61 | +} |
| 62 | + |
| 63 | +namespace flatbuffers { |
| 64 | +void LogCompilerWarn(const std::string& warn) { |
| 65 | + Warn(static_cast<const flatbuffers::FlatCompiler*>(nullptr), warn, true); |
| 66 | +} |
| 67 | +void LogCompilerError(const std::string& err) { |
| 68 | + Error(static_cast<const flatbuffers::FlatCompiler*>(nullptr), err, false, |
| 69 | + true); |
| 70 | +} |
| 71 | +} // namespace flatbuffers |
| 72 | + |
| 73 | +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| 74 | + // Reserve one byte for Parser flags and one byte for repetition counter. |
| 75 | + if (size < 3) return 0; |
| 76 | + const uint8_t flags = data[0]; |
| 77 | + (void)data[1]; // reserved |
| 78 | + data += 2; |
| 79 | + size -= 2; // bypass |
| 80 | + |
| 81 | + const std::string original(reinterpret_cast<const char*>(data), size); |
| 82 | + auto input = std::string(original.c_str()); // until '\0' |
| 83 | + if (input.size() < kMinInputLength || input.size() > kMaxInputLength) |
| 84 | + return 0; |
| 85 | + |
| 86 | + flatbuffers::IDLOptions opts; |
| 87 | + opts.strict_json = (flags & flags_strict_json); |
| 88 | + opts.skip_unexpected_fields_in_json = |
| 89 | + (flags & flags_skip_unexpected_fields_in_json); |
| 90 | + opts.allow_non_utf8 = (flags & flags_allow_non_utf8); |
| 91 | + |
| 92 | + flatbuffers::Parser parser(opts); |
| 93 | + |
| 94 | + // Guarantee 0-termination in the input. |
| 95 | + auto parse_input = input.c_str(); |
| 96 | + |
| 97 | + // Parse the input schema |
| 98 | + if (parser.Parse(parse_input)) { |
| 99 | + parser.Serialize(); |
| 100 | + const uint8_t* buf = parser.builder_.GetBufferPointer(); |
| 101 | + flatbuffers::Verifier verifier(buf, |
| 102 | + parser.builder_.GetSize()); |
| 103 | + TEST_EQ(true, reflection::VerifySchemaBuffer(verifier)); |
| 104 | + |
| 105 | + auto root = flatbuffers::GetRoot<flatbuffers::Table>(buf); |
| 106 | + if (verifier.VerifyTableStart(buf) && root->VerifyTableStart(verifier)) { |
| 107 | + if (parser.root_struct_def_) { |
| 108 | + std::string json_output; |
| 109 | + flatbuffers::GenText(parser, parser.builder_.GetBufferPointer(), |
| 110 | + &json_output); |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + std::string temp_filename = "fuzzer_generated"; |
| 115 | + |
| 116 | + const std::string flatbuffers_version(flatbuffers::FLATBUFFERS_VERSION()); |
| 117 | + std::vector<std::unique_ptr<flatbuffers::CodeGenerator>> generators; |
| 118 | + generators.emplace_back(flatbuffers::NewBinaryCodeGenerator()); |
| 119 | + generators.emplace_back(flatbuffers::NewCppCodeGenerator()); |
| 120 | + generators.emplace_back(flatbuffers::NewCSharpCodeGenerator()); |
| 121 | + generators.emplace_back(flatbuffers::NewDartCodeGenerator()); |
| 122 | + generators.emplace_back(flatbuffers::NewFBSCodeGenerator()); |
| 123 | + generators.emplace_back(flatbuffers::NewGoCodeGenerator()); |
| 124 | + generators.emplace_back(flatbuffers::NewJavaCodeGenerator()); |
| 125 | + generators.emplace_back(flatbuffers::NewJsonSchemaCodeGenerator()); |
| 126 | + generators.emplace_back(flatbuffers::NewKotlinCodeGenerator()); |
| 127 | + generators.emplace_back(flatbuffers::NewKotlinKMPCodeGenerator()); |
| 128 | + generators.emplace_back(flatbuffers::NewLobsterCodeGenerator()); |
| 129 | + generators.emplace_back(flatbuffers::NewLuaBfbsGenerator(flatbuffers_version)); |
| 130 | + generators.emplace_back(flatbuffers::NewNimBfbsGenerator(flatbuffers_version)); |
| 131 | + generators.emplace_back(flatbuffers::NewPythonCodeGenerator()); |
| 132 | + generators.emplace_back(flatbuffers::NewPhpCodeGenerator()); |
| 133 | + generators.emplace_back(flatbuffers::NewRustCodeGenerator()); |
| 134 | + generators.emplace_back(flatbuffers::NewTextCodeGenerator()); |
| 135 | + generators.emplace_back(flatbuffers::NewSwiftCodeGenerator()); |
| 136 | + generators.emplace_back(flatbuffers::NewTsCodeGenerator()); |
| 137 | + |
| 138 | + for (auto& gen : generators) { |
| 139 | + auto p = gen.get(); |
| 140 | + std::string temp_path = "/tmp/"; |
| 141 | + auto status = p->GenerateCode(parser, temp_path, "fuzzer_generated"); |
| 142 | + if (status != flatbuffers::CodeGenerator::Status::OK) { |
| 143 | + TEST_OUTPUT_LINE("GenerateCode failed %d", status); |
| 144 | + } |
| 145 | + |
| 146 | + // test gRPC code generation |
| 147 | + auto grpc_status = |
| 148 | + p->GenerateGrpcCode(parser, temp_path, "fuzzer_generated"); |
| 149 | + if (grpc_status != flatbuffers::CodeGenerator::Status::OK) { |
| 150 | + TEST_OUTPUT_LINE("GenerateGrpcCode failed %d", grpc_status); |
| 151 | + } |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + return 0; |
| 156 | +} |
0 commit comments