From 50264f6f41b43d7840ef7b79e86b598dc95ab9f3 Mon Sep 17 00:00:00 2001 From: Justin Davis Date: Wed, 17 Dec 2025 22:59:37 -0500 Subject: [PATCH 1/3] push code around to be more decoupled --- include/flatbuffers/file_manager.h | 19 +++----------- src/file_manager.cpp | 26 ++++++++++++++----- src/file_name_manager.cpp | 41 +++++++++++++++++++----------- src/flatc_main.cpp | 4 +-- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/include/flatbuffers/file_manager.h b/include/flatbuffers/file_manager.h index bafe6f29b97..c3cc4c60059 100644 --- a/include/flatbuffers/file_manager.h +++ b/include/flatbuffers/file_manager.h @@ -18,6 +18,7 @@ #define FLATBUFFERS_FILE_MANAGER_H_ #include +#include #include #include @@ -48,22 +49,8 @@ class FileSaver { FileSaver& operator=(FileSaver&&) = default; }; -class RealFileSaver final : public FileSaver { - public: - bool SaveFile(const char* name, const char* buf, size_t len, - bool binary) final; -}; - -class FileNameSaver final : public FileSaver { - public: - bool SaveFile(const char* name, const char* buf, size_t len, - bool binary) final; - - void Finish() final; - - private: - std::set file_names_{}; -}; +std::unique_ptr CreateFileSaver(); +std::unique_ptr CreateFileNameCollector(); } // namespace flatbuffers diff --git a/src/file_manager.cpp b/src/file_manager.cpp index 13b1580af04..467325a647d 100644 --- a/src/file_manager.cpp +++ b/src/file_manager.cpp @@ -22,12 +22,26 @@ namespace flatbuffers { -bool RealFileSaver::SaveFile(const char* name, const char* buf, size_t len, - bool binary) { - std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out); - if (!ofs.is_open()) return false; - ofs.write(buf, len); - return !ofs.bad(); +class RealFileSaver final : public FileSaver { + public: + bool SaveFile(const char* name, const char* buf, size_t len, + bool binary) final { + std::ofstream ofs{name, + binary ? std::ofstream::binary : std::ofstream::out}; + + if (!ofs.is_open()) { + return false; + } + + ofs.write(buf, len); + + return !ofs.bad(); + } +}; + +std::unique_ptr CreateFileSaver() { + // compiler limitations mean we can't use std::make_unique + return std::unique_ptr{new RealFileSaver()}; } } // namespace flatbuffers diff --git a/src/file_name_manager.cpp b/src/file_name_manager.cpp index aad63de8c6b..313dc9e6a9b 100644 --- a/src/file_name_manager.cpp +++ b/src/file_name_manager.cpp @@ -21,24 +21,35 @@ namespace flatbuffers { -bool FileNameSaver::SaveFile(const char* name, const char* buf, size_t len, - bool binary) { - (void)buf; - (void)len; - (void)binary; +class FileNameSaver final : public FileSaver { + public: + bool SaveFile(const char* name, const char* buf, size_t len, + bool binary) final { + (void)buf; + (void)len; + (void)binary; + + std::ignore = file_names_.insert(name); + + // we want to simulate always successful save + return true; + } - std::ignore = file_names_.insert(name); + void Finish() final { + for (const auto& file_name : file_names_) { + // Just print the file names to standard output. + // No actual file is created. + std::cout << file_name << "\n"; + } + } - // we want to simulate always successful save - return true; -} + private: + std::set file_names_{}; +}; -void FileNameSaver::Finish() { - for (const auto& file_name : file_names_) { - // Just print the file names to standard output. - // No actual file is created. - std::cout << file_name << "\n"; - } +std::unique_ptr CreateFileNameCollector() { + // compiler limitations mean we can't use std::make_unique + return std::unique_ptr{new FileNameSaver()}; } } // namespace flatbuffers diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index ce9b8c4a4ed..bd35f56635b 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -187,9 +187,9 @@ int main(int argc, const char* argv[]) { // this exists here to ensure file_saver outlives the compilation process std::unique_ptr file_saver; if (options.file_names_only) { - file_saver.reset(new flatbuffers::FileNameSaver{}); + file_saver = flatbuffers::CreateFileNameCollector(); } else { - file_saver.reset(new flatbuffers::RealFileSaver{}); + file_saver = flatbuffers::CreateFileSaver(); } options.opts.file_saver = file_saver.get(); From 1f545c3a99bdfa522eddc565cf211abba8e45ac6 Mon Sep 17 00:00:00 2001 From: Justin Davis Date: Wed, 4 Feb 2026 08:36:39 -0500 Subject: [PATCH 2/3] address #8902 --- src/idl_gen_binary.cpp | 3 +++ tests/fuzzer/flatbuffers_codegen_fuzzer.cc | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/idl_gen_binary.cpp b/src/idl_gen_binary.cpp index 2afc6f77c56..2089ae96c98 100644 --- a/src/idl_gen_binary.cpp +++ b/src/idl_gen_binary.cpp @@ -41,6 +41,9 @@ static std::string BinaryFileName(const Parser& parser, const std::string& path, static bool GenerateBinary(const Parser& parser, const std::string& path, const std::string& file_name) { + // sanity check we have a file saver + if (!parser.opts.file_saver) return false; + if (parser.opts.use_flexbuffers) { auto data_vec = parser.flex_builder_.GetBuffer(); auto data_ptr = reinterpret_cast(data(data_vec)); diff --git a/tests/fuzzer/flatbuffers_codegen_fuzzer.cc b/tests/fuzzer/flatbuffers_codegen_fuzzer.cc index 2558f82809e..d2182005d51 100644 --- a/tests/fuzzer/flatbuffers_codegen_fuzzer.cc +++ b/tests/fuzzer/flatbuffers_codegen_fuzzer.cc @@ -90,6 +90,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { (flags & flags_skip_unexpected_fields_in_json); opts.allow_non_utf8 = (flags & flags_allow_non_utf8); + // make sure we have a file saver + opts.file_saver = flatbuffers::CreateFileSaver(); + flatbuffers::Parser parser(opts); // Guarantee 0-termination in the input. From eb5f72fd314950f9b2bbbcdafd6b43eecd536aed Mon Sep 17 00:00:00 2001 From: Justin Davis Date: Wed, 4 Feb 2026 11:59:46 -0500 Subject: [PATCH 3/3] unique_ptr --- tests/fuzzer/flatbuffers_codegen_fuzzer.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fuzzer/flatbuffers_codegen_fuzzer.cc b/tests/fuzzer/flatbuffers_codegen_fuzzer.cc index d2182005d51..a005b60997c 100644 --- a/tests/fuzzer/flatbuffers_codegen_fuzzer.cc +++ b/tests/fuzzer/flatbuffers_codegen_fuzzer.cc @@ -91,7 +91,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { opts.allow_non_utf8 = (flags & flags_allow_non_utf8); // make sure we have a file saver - opts.file_saver = flatbuffers::CreateFileSaver(); + auto saver = flatbuffers::CreateFileSaver(); + opts.file_saver = saver.get(); flatbuffers::Parser parser(opts);