diff --git a/test/tools/ossfuzz/CMakeLists.txt b/test/tools/ossfuzz/CMakeLists.txt
index 265533397..e9e95d108 100644
--- a/test/tools/ossfuzz/CMakeLists.txt
+++ b/test/tools/ossfuzz/CMakeLists.txt
@@ -9,6 +9,7 @@ add_dependencies(ossfuzz
)
if (OSSFUZZ)
+ add_subdirectory(lpsolver)
add_custom_target(ossfuzz_proto)
add_dependencies(ossfuzz_proto
sol_proto_ossfuzz
@@ -23,6 +24,13 @@ if (OSSFUZZ)
endif()
if (OSSFUZZ)
+ add_executable(lpsolver_ossfuzz
+ LPSolverFuzzer.cpp
+ LPSolverCustomMutatorInterface.cpp
+ )
+ target_link_libraries(lpsolver_ossfuzz PRIVATE solutil lpsolvergen)
+ set_target_properties(lpsolver_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
+
add_executable(solc_ossfuzz
solc_ossfuzz.cpp
../fuzzer_common.cpp
diff --git a/test/tools/ossfuzz/LPSolverCustomMutatorInterface.cpp b/test/tools/ossfuzz/LPSolverCustomMutatorInterface.cpp
new file mode 100644
index 000000000..87c68aad0
--- /dev/null
+++ b/test/tools/ossfuzz/LPSolverCustomMutatorInterface.cpp
@@ -0,0 +1,71 @@
+/*
+ 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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#include
+#include
+
+#include
+
+using namespace std;
+using namespace solidity::test::fuzzer::lpsolver;
+
+// Prototype as we can't use the FuzzerInterface.h header.
+extern "C" size_t LLVMFuzzerMutate(uint8_t* _data, size_t _size, size_t _maxSize);
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* _data, size_t size, size_t _maxSize, unsigned int seed);
+
+namespace
+{
+/// Define LP Solver's custom mutator by implementing libFuzzer's
+/// custom mutator external interface.
+extern "C" size_t LLVMFuzzerCustomMutator(
+ uint8_t* _data,
+ size_t _size,
+ size_t _maxSize,
+ unsigned int _seed
+)
+{
+ solAssert(_data, "libFuzzerInterface: libFuzzer supplied bad buffer");
+ if (_maxSize <= _size || _size == 0)
+ return LLVMFuzzerMutate(_data, _size, _maxSize);
+ return LPSolverCustomMutatorInterface{_data, _size, _maxSize, _seed}.generate();
+}
+}
+
+LPSolverCustomMutatorInterface::LPSolverCustomMutatorInterface(
+ uint8_t* _data,
+ size_t _size,
+ size_t _maxSize,
+ unsigned int _seed
+):
+ data(_data),
+ size(_size),
+ maxMutantSize(_maxSize),
+ generator(make_shared(_seed))
+{}
+
+size_t LPSolverCustomMutatorInterface::generate()
+{
+ string testCase = generator->generate();
+ solAssert(
+ !testCase.empty() && data,
+ "Solc custom mutator: Invalid mutant or memory pointer"
+ );
+ size_t mutantSize = min(testCase.size(), maxMutantSize - 1);
+ mempcpy(data, testCase.data(), mutantSize);
+ return mutantSize;
+}
diff --git a/test/tools/ossfuzz/LPSolverCustomMutatorInterface.h b/test/tools/ossfuzz/LPSolverCustomMutatorInterface.h
new file mode 100644
index 000000000..eb9177641
--- /dev/null
+++ b/test/tools/ossfuzz/LPSolverCustomMutatorInterface.h
@@ -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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+/**
+ * Implements libFuzzer's custom mutator interface for LP Solver fuzzer.
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace solidity::test::fuzzer::lpsolver
+{
+struct LPSolverCustomMutatorInterface
+{
+ LPSolverCustomMutatorInterface(uint8_t* _data, size_t _size, size_t _maxSize, unsigned _seed);
+ /// Generates LP Solver constraints, copies it into buffer
+ /// provided by libFuzzer and @returns size of the test program.
+ size_t generate();
+
+ /// Raw pointer to libFuzzer provided input
+ uint8_t* data;
+ /// Size of libFuzzer provided input
+ size_t size;
+ /// Maximum length of mutant specified by libFuzzer
+ size_t maxMutantSize;
+ /// Constraint generator handle
+ std::shared_ptr generator;
+};
+}
diff --git a/test/tools/ossfuzz/LPSolverFuzzer.cpp b/test/tools/ossfuzz/LPSolverFuzzer.cpp
new file mode 100644
index 000000000..9779458cb
--- /dev/null
+++ b/test/tools/ossfuzz/LPSolverFuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ 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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#include
+#include
+
+using namespace std;
+
+// Prototype as we can't use the FuzzerInterface.h header.
+extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size);
+
+extern "C" int LLVMFuzzerTestOneInput(uint8_t const* , size_t )
+{
+ // TODO: Invoke LP solver and Z3 on constraints provided by fuzzer interface,
+ // comparing their outcomes.
+ return 0;
+}
diff --git a/test/tools/ossfuzz/lpsolver/CMakeLists.txt b/test/tools/ossfuzz/lpsolver/CMakeLists.txt
new file mode 100644
index 000000000..167aa6e45
--- /dev/null
+++ b/test/tools/ossfuzz/lpsolver/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(sources
+ ConstraintGenerator.cpp
+ ConstraintGenerator.h
+ FuzzerSolverInterface.cpp
+ FuzzerSolverInterface.h
+)
+add_library(lpsolvergen)
+target_sources(lpsolvergen
+ PUBLIC
+ ${sources}
+)
+target_link_libraries(lpsolvergen PUBLIC solutil)
diff --git a/test/tools/ossfuzz/lpsolver/ConstraintGenerator.cpp b/test/tools/ossfuzz/lpsolver/ConstraintGenerator.cpp
new file mode 100644
index 000000000..852202378
--- /dev/null
+++ b/test/tools/ossfuzz/lpsolver/ConstraintGenerator.cpp
@@ -0,0 +1,41 @@
+/*
+ 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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#include
+
+using namespace std;
+using namespace solidity::test::fuzzer::lpsolver;
+
+ConstraintGenerator::ConstraintGenerator(unsigned int _seed)
+{
+ prng = make_shared(_seed);
+}
+
+string ConstraintGenerator::generate()
+{
+ string constraint;
+ for (int i = 0; i < numConstraints(); i++)
+ {
+ string sep;
+ for (int j = 0; j < numFactors(); j++)
+ {
+ constraint += sep + to_string(randomInteger());
+ if (sep.empty())
+ sep = ", ";
+ }
+ constraint += "\n";
+ }
+ return constraint;
+}
diff --git a/test/tools/ossfuzz/lpsolver/ConstraintGenerator.h b/test/tools/ossfuzz/lpsolver/ConstraintGenerator.h
new file mode 100644
index 000000000..1e1719b3b
--- /dev/null
+++ b/test/tools/ossfuzz/lpsolver/ConstraintGenerator.h
@@ -0,0 +1,65 @@
+/*
+ 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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+/*
+ * Generates an integer matrix of dimension n x m
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace solidity::test::fuzzer::lpsolver
+{
+
+using RandomEngine = std::mt19937;
+using Distribution = std::uniform_int_distribution;
+
+struct ConstraintGenerator
+{
+ explicit ConstraintGenerator(unsigned int _seed);
+
+ /// @returns generated constraint.
+ std::string generate();
+
+ /// @returns random number of factors.
+ int numFactors()
+ {
+ return Distribution(s_minFactors, s_maxFactors)(*prng);
+ }
+
+ /// @returns random number of constraints.
+ int numConstraints()
+ {
+ return Distribution(s_minConstraints, s_maxConstraints)(*prng);
+ }
+
+ /// @returns an integer chosen uniformly at random.
+ int randomInteger()
+ {
+ return Distribution(std::numeric_limits::min(), std::numeric_limits::max())(*prng);
+ }
+
+ std::shared_ptr prng;
+
+ static constexpr int s_minFactors = 2;
+ static constexpr int s_maxFactors = 10;
+ static constexpr int s_minConstraints = 1;
+ static constexpr int s_maxConstraints = 10;
+};
+
+}
diff --git a/test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.cpp b/test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.cpp
new file mode 100644
index 000000000..efd9911eb
--- /dev/null
+++ b/test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.cpp
@@ -0,0 +1,66 @@
+/*
+ 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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#include
+
+using namespace solidity::test::fuzzer::lpsolver;
+using namespace solidity::util;
+using namespace std;
+
+FuzzerSolverInterface::FuzzerSolverInterface()
+{
+ m_solvingState.variableNames.emplace_back("");
+}
+
+LinearExpression FuzzerSolverInterface::constant(rational _value)
+{
+ return LinearExpression::factorForVariable(0, _value);
+}
+
+LinearExpression FuzzerSolverInterface::variable(
+ rational _factor,
+ string const& _variable
+)
+{
+ return LinearExpression::factorForVariable(variableIndex(_variable), _factor);
+}
+
+void FuzzerSolverInterface::addLEConstraint(LinearExpression _lhs)
+{
+ m_solvingState.constraints.push_back({move(_lhs), false});
+}
+
+void FuzzerSolverInterface::addEQConstraint(LinearExpression _lhs)
+{
+ m_solvingState.constraints.push_back({move(_lhs), true});
+}
+
+solution FuzzerSolverInterface::check()
+{
+ return m_solver.check(m_solvingState);
+}
+
+size_t FuzzerSolverInterface::variableIndex(string const& _name)
+{
+ if (m_solvingState.variableNames.empty())
+ m_solvingState.variableNames.emplace_back("");
+ auto index = findOffset(m_solvingState.variableNames, _name);
+ if (!index)
+ {
+ index = m_solvingState.variableNames.size();
+ m_solvingState.variableNames.emplace_back(_name);
+ }
+ return *index;
+}
diff --git a/test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.h b/test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.h
new file mode 100644
index 000000000..655926ad1
--- /dev/null
+++ b/test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.h
@@ -0,0 +1,70 @@
+/*
+ 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 .
+*/
+// SPDX-License-Identifier: GPL-3.0
+/**
+ * Implements the Fuzzer-Solver interface.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+
+namespace solidity::test::fuzzer::lpsolver
+{
+
+using solution = std::pair<
+ solidity::util::LPResult,
+ std::map
+>;
+
+class FuzzerSolverInterface
+{
+public:
+ FuzzerSolverInterface();
+
+ /// @returns constant rational.
+ solidity::util::LinearExpression constant(solidity::util::rational _rationalConstant);
+
+ /// @returns linear expression that equals zero.
+ solidity::util::LinearExpression zero()
+ {
+ return constant(0);
+ }
+
+ /// @returns product of a rational factor and variable.
+ solidity::util::LinearExpression variable(
+ solidity::util::rational _factor,
+ std::string const& _variable
+ );
+
+ /// Adds less-than-equal-zero constraint to solver.
+ void addLEConstraint(solidity::util::LinearExpression _lhs);
+
+ /// Adds equal-to-zero constraint to solver.
+ void addEQConstraint(solidity::util::LinearExpression _lhs);
+
+ /// Queries LP solver and @returns solution.
+ solution check();
+
+private:
+ /// Adds variable if necessary to LP solver state and @returns index of variable.
+ size_t variableIndex(std::string const& _name);
+
+ solidity::util::LPSolver m_solver;
+ solidity::util::SolvingState m_solvingState;
+};
+}