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