diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt
index a799bd736..139c9a624 100644
--- a/test/tools/ossfuzz/CMakeLists.txt
+++ b/test/tools/ossfuzz/CMakeLists.txt
@@ -12,6 +12,7 @@ add_dependencies(ossfuzz
if (OSSFUZZ)
add_custom_target(ossfuzz_proto)
add_dependencies(ossfuzz_proto
+ sol_import_proto_ossfuzz
sol_proto_ossfuzz
yul_proto_ossfuzz
yul_proto_diff_ossfuzz
@@ -124,6 +125,23 @@ if (OSSFUZZ)
)
set_target_properties(sol_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
target_compile_options(sol_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion)
+
+ add_executable(sol_import_proto_ossfuzz
+ SolImportProtoFuzzer.cpp
+ SolImportProtoConverter.cpp
+ solImportProto.pb.cc
+ ../fuzzer_common.cpp
+ )
+ target_include_directories(sol_import_proto_ossfuzz PRIVATE
+ /usr/include/libprotobuf-mutator
+ )
+ target_link_libraries(sol_import_proto_ossfuzz PRIVATE solidity libsolc
+ protobuf-mutator-libfuzzer.a
+ protobuf-mutator.a
+ protobuf.a
+ )
+ set_target_properties(sol_import_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
+ target_compile_options(sol_import_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion)
else()
add_library(solc_opt_ossfuzz
solc_opt_ossfuzz.cpp
diff --git a/test/tools/ossfuzz/SolImportProtoConverter.cpp b/test/tools/ossfuzz/SolImportProtoConverter.cpp
new file mode 100644
index 000000000..56e5eb896
--- /dev/null
+++ b/test/tools/ossfuzz/SolImportProtoConverter.cpp
@@ -0,0 +1,60 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+
+#include
+
+#include
+
+using namespace solidity::test::solimportprotofuzzer;
+using namespace std;
+
+map ProtoConverter::sourceCodeMap(Test const& _input)
+{
+ // Setup random number generator
+ m_randomGen = make_unique(_input.seed());
+ m_numSources = _input.source_size();
+ unsigned sourceIndex = 0;
+ for (auto const& source: _input.source())
+ m_sourceMap["i" + to_string(sourceIndex++) + ".sol"] = visit(source);
+ return m_sourceMap;
+}
+
+string ProtoConverter::visit(Source const& _source)
+{
+ // A source file may import itself and any of the
+ // other source files.
+ unsigned numImports = _source.num_imports() % (m_numSources + 1);
+ string sourceCode = {};
+ set importSet;
+ for (unsigned i = 0; i < numImports; i++)
+ {
+ unsigned sourceIndex = randomNum() % m_numSources;
+ // Avoid duplicate imports
+ if (importSet.count(sourceIndex))
+ continue;
+ else
+ importSet.insert(sourceIndex);
+ string sourceName = "i" + to_string(sourceIndex) + ".sol";
+ string importName = "I" + to_string(sourceIndex);
+ sourceCode += "import \"" + sourceName + "\" as " + importName + ";\n";
+ }
+ sourceCode += _source.code();
+ boost::range::remove_erase_if(sourceCode, [=](char c) -> bool {
+ return !(std::isprint(c) || c == '\n');
+ });
+ return sourceCode;
+}
\ No newline at end of file
diff --git a/test/tools/ossfuzz/SolImportProtoConverter.h b/test/tools/ossfuzz/SolImportProtoConverter.h
new file mode 100644
index 000000000..668a5fbe0
--- /dev/null
+++ b/test/tools/ossfuzz/SolImportProtoConverter.h
@@ -0,0 +1,63 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+
+#include
+
+#include
+
+namespace solidity::test::solimportprotofuzzer
+{
+
+/// Random number generator that is seeded with a fuzzer
+/// supplied unsigned integer.
+struct SolRandomNumGenerator
+{
+ using RandomEngine = std::mt19937_64;
+
+ explicit SolRandomNumGenerator(unsigned _seed): m_random(RandomEngine(_seed)) {}
+
+ /// @returns a pseudo random unsigned integer
+ unsigned operator()()
+ {
+ return m_random();
+ }
+
+ RandomEngine m_random;
+};
+
+class ProtoConverter
+{
+public:
+ ProtoConverter() {}
+ ProtoConverter(ProtoConverter const&) = delete;
+ ProtoConverter(ProtoConverter&&) = delete;
+ std::map sourceCodeMap(Test const& _input);
+private:
+ std::string visit(Source const& _source);
+ unsigned randomNum()
+ {
+ return (*m_randomGen)();
+ }
+
+ /// Number of source files declared in test file
+ unsigned m_numSources = 0;
+ /// Source code map to be passed to compiler stack
+ std::map m_sourceMap;
+ /// Smart pointer to a random number generator seeded by fuzzing input
+ std::unique_ptr m_randomGen;
+};
+}
\ No newline at end of file
diff --git a/test/tools/ossfuzz/SolImportProtoFuzzer.cpp b/test/tools/ossfuzz/SolImportProtoFuzzer.cpp
new file mode 100644
index 000000000..c8ea5f71c
--- /dev/null
+++ b/test/tools/ossfuzz/SolImportProtoFuzzer.cpp
@@ -0,0 +1,46 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+using namespace solidity::test::solimportprotofuzzer;
+using namespace std;
+
+DEFINE_PROTO_FUZZER(Test const& _input)
+{
+ auto sourceMap = ProtoConverter{}.sourceCodeMap(_input);
+ if (char const* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
+ {
+ // With libFuzzer binary run this to generate a YUL source file x.yul:
+ // PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input
+ ofstream of(dump_path);
+ for (const auto &[key, value]: sourceMap)
+ {
+ string header = "==== Source: " + key + " ====\n";
+ of.write(header.data(), header.size());
+ of.write(value.data(), value.size());
+ of.write("\n", 1);
+ }
+ }
+ FuzzerUtil::testCompiler(sourceMap, false, _input.ByteSizeLong());
+}
diff --git a/test/tools/ossfuzz/solImportProto.proto b/test/tools/ossfuzz/solImportProto.proto
new file mode 100644
index 000000000..19af5b894
--- /dev/null
+++ b/test/tools/ossfuzz/solImportProto.proto
@@ -0,0 +1,30 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+
+syntax = "proto2";
+
+message Source {
+ required uint64 num_imports = 1;
+ required string code = 2;
+}
+
+message Test {
+ repeated Source source = 1;
+ required uint64 seed = 2;
+}
+
+package solidity.test.solimportprotofuzzer;