mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Differentially fuzz against z3.
This commit is contained in:
parent
3e88f7f85a
commit
ea50fee663
@ -28,7 +28,7 @@ if (OSSFUZZ)
|
|||||||
LPSolverFuzzer.cpp
|
LPSolverFuzzer.cpp
|
||||||
LPSolverCustomMutatorInterface.cpp
|
LPSolverCustomMutatorInterface.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(lpsolver_ossfuzz PRIVATE solutil lpsolvergen)
|
target_link_libraries(lpsolver_ossfuzz PRIVATE solutil lpsolvergen z3)
|
||||||
set_target_properties(lpsolver_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
set_target_properties(lpsolver_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||||
|
|
||||||
add_executable(solc_ossfuzz
|
add_executable(solc_ossfuzz
|
||||||
|
@ -113,21 +113,12 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
|||||||
auto constraints = parseConstraints(input);
|
auto constraints = parseConstraints(input);
|
||||||
if (constraints.has_value())
|
if (constraints.has_value())
|
||||||
{
|
{
|
||||||
// TODO: Z3 on constraints provided by fuzzer interface and comparing its outcome
|
|
||||||
// with LP solver.
|
|
||||||
FuzzerSolverInterface solverWithoutModels(/*supportModels=*/false);
|
|
||||||
FuzzerSolverInterface solverWithModels(/*supportModels=*/true);
|
FuzzerSolverInterface solverWithModels(/*supportModels=*/true);
|
||||||
|
if (!solverWithModels.differentialCheck(constraints.value()))
|
||||||
solverWithoutModels.addConstraints(constraints.value());
|
|
||||||
string resultWithoutModels = solverWithoutModels.checkResult();
|
|
||||||
solverWithModels.addConstraints(constraints.value());
|
|
||||||
string resultWithModels = solverWithModels.checkResult();
|
|
||||||
|
|
||||||
if (resultWithoutModels != resultWithModels)
|
|
||||||
{
|
{
|
||||||
cout << resultWithoutModels << endl;
|
cout << solverWithModels.m_lpResult << endl;
|
||||||
cout << resultWithModels << endl;
|
cout << solverWithModels.m_z3Result << endl;
|
||||||
solAssert(false, "LP result without models did not match with result with models.");
|
solAssert(false, "LP result did not match with z3 result.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,21 @@
|
|||||||
|
|
||||||
#include <range/v3/view/enumerate.hpp>
|
#include <range/v3/view/enumerate.hpp>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
using namespace solidity::test::fuzzer::lpsolver;
|
using namespace solidity::test::fuzzer::lpsolver;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace z3;
|
||||||
|
|
||||||
FuzzerSolverInterface::FuzzerSolverInterface(bool _supportModels):
|
FuzzerSolverInterface::FuzzerSolverInterface(bool _supportModels):
|
||||||
m_solver(_supportModels)
|
m_lpSolver(_supportModels),
|
||||||
|
m_z3Solver(m_z3Ctx)
|
||||||
{
|
{
|
||||||
m_solvingState.variableNames.emplace_back("");
|
m_lpSolvingState.variableNames.emplace_back("");
|
||||||
|
params z3Params(m_z3Ctx);
|
||||||
|
z3Params.set(":timeout", static_cast<unsigned>(10)); // in milliseconds
|
||||||
|
m_z3Solver.set(z3Params);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearExpression FuzzerSolverInterface::linearExpression(vector<int> _factors)
|
LinearExpression FuzzerSolverInterface::linearExpression(vector<int> _factors)
|
||||||
@ -36,26 +43,75 @@ LinearExpression FuzzerSolverInterface::linearExpression(vector<int> _factors)
|
|||||||
return lexp;
|
return lexp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuzzerSolverInterface::addConstraint(pair<bool, vector<int>> _constraint)
|
void FuzzerSolverInterface::addLPConstraint(pair<bool, vector<int>> _constraint)
|
||||||
{
|
{
|
||||||
m_solvingState.constraints.push_back({linearExpression(move(_constraint.second)), _constraint.first});
|
m_lpSolvingState.constraints.push_back({linearExpression(move(_constraint.second)), _constraint.first});
|
||||||
}
|
}
|
||||||
|
|
||||||
void FuzzerSolverInterface::addConstraints(vector<pair<bool, vector<int>>> _constraints)
|
void FuzzerSolverInterface::addZ3Constraint(pair<bool, vector<int>> _constraint)
|
||||||
|
{
|
||||||
|
bool isEquality = _constraint.first;
|
||||||
|
expr reduce = m_z3Ctx.real_val(0);
|
||||||
|
for (auto&& [index, value]: _constraint.second | ranges::views::enumerate)
|
||||||
|
{
|
||||||
|
if (index != 0 && value != 0)
|
||||||
|
{
|
||||||
|
string varName = "x" + to_string(index - 1);
|
||||||
|
expr var = m_z3Ctx.real_const(varName.c_str());
|
||||||
|
expr factor = m_z3Ctx.int_val(value);
|
||||||
|
reduce = reduce + var * factor;
|
||||||
|
m_z3Solver.add(var >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isEquality)
|
||||||
|
m_z3Solver.add(reduce == _constraint.second[0]);
|
||||||
|
else
|
||||||
|
m_z3Solver.add(reduce <= _constraint.second[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FuzzerSolverInterface::addLPConstraints(vector<pair<bool, vector<int>>> _constraints)
|
||||||
{
|
{
|
||||||
for (auto c: _constraints)
|
for (auto c: _constraints)
|
||||||
addConstraint(c);
|
addLPConstraint(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
solution FuzzerSolverInterface::check()
|
void FuzzerSolverInterface::addZ3Constraints(vector<pair<bool, vector<int>>> _constraints)
|
||||||
{
|
{
|
||||||
return m_solver.check(m_solvingState);
|
for (auto c: _constraints)
|
||||||
|
addZ3Constraint(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
string FuzzerSolverInterface::checkResult()
|
solution FuzzerSolverInterface::checkLP()
|
||||||
{
|
{
|
||||||
auto r = check();
|
return m_lpSolver.check(m_lpSolvingState);
|
||||||
return lpResult(r.first);
|
}
|
||||||
|
|
||||||
|
check_result FuzzerSolverInterface::checkZ3()
|
||||||
|
{
|
||||||
|
return m_z3Solver.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
string FuzzerSolverInterface::checkLPResult()
|
||||||
|
{
|
||||||
|
m_lpResult = lpResult(checkLP().first);
|
||||||
|
return m_lpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
string FuzzerSolverInterface::checkZ3Result()
|
||||||
|
{
|
||||||
|
m_z3Result = z3Result(checkZ3());
|
||||||
|
return m_z3Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FuzzerSolverInterface::differentialCheck(vector<pair<bool, vector<int>>> _constraints)
|
||||||
|
{
|
||||||
|
addLPConstraints(_constraints);
|
||||||
|
addZ3Constraints(_constraints);
|
||||||
|
string z3Result = checkZ3Result();
|
||||||
|
string lpResult = checkLPResult();
|
||||||
|
bool checkFailed = ((z3Result == "infeasible") && (lpResult == "feasible")) ||
|
||||||
|
((z3Result == "feasible") && (lpResult == "infeasible"));
|
||||||
|
return !checkFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
string FuzzerSolverInterface::lpResult(LPResult _result)
|
string FuzzerSolverInterface::lpResult(LPResult _result)
|
||||||
@ -72,3 +128,18 @@ string FuzzerSolverInterface::lpResult(LPResult _result)
|
|||||||
return "infeasible";
|
return "infeasible";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string FuzzerSolverInterface::z3Result(check_result _result)
|
||||||
|
{
|
||||||
|
switch (_result)
|
||||||
|
{
|
||||||
|
case check_result::unsat:
|
||||||
|
return "infeasible";
|
||||||
|
case check_result::sat:
|
||||||
|
return "feasible";
|
||||||
|
case check_result::unknown:
|
||||||
|
return "unknown";
|
||||||
|
default:
|
||||||
|
solAssert(false, "Invalid Z3 result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include <libsolutil/LP.h>
|
#include <libsolutil/LP.h>
|
||||||
#include <libsolutil/LinearExpression.h>
|
#include <libsolutil/LinearExpression.h>
|
||||||
|
|
||||||
|
#include <z3++.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace solidity::test::fuzzer::lpsolver
|
namespace solidity::test::fuzzer::lpsolver
|
||||||
@ -37,25 +39,48 @@ public:
|
|||||||
FuzzerSolverInterface(bool _supportModels);
|
FuzzerSolverInterface(bool _supportModels);
|
||||||
|
|
||||||
/// Adds @param _constraint to LP solver.
|
/// Adds @param _constraint to LP solver.
|
||||||
void addConstraint(std::pair<bool, std::vector<int>> _constraint);
|
void addLPConstraint(std::pair<bool, std::vector<int>> _constraint);
|
||||||
|
|
||||||
|
/// Adds @param _constraint to Z3 solver.
|
||||||
|
void addZ3Constraint(std::pair<bool, std::vector<int>> _constraint);
|
||||||
|
|
||||||
/// Adds @param _constraints to LP solver.
|
/// Adds @param _constraints to LP solver.
|
||||||
void addConstraints(std::vector<std::pair<bool, std::vector<int>>> _constraints);
|
void addLPConstraints(std::vector<std::pair<bool, std::vector<int>>> _constraints);
|
||||||
|
|
||||||
|
/// Adds @param _constraints to Z3 solver.
|
||||||
|
void addZ3Constraints(std::vector<std::pair<bool, std::vector<int>>> _constraints);
|
||||||
|
|
||||||
/// @returns linear expression created from @param _factors.
|
/// @returns linear expression created from @param _factors.
|
||||||
solidity::util::LinearExpression linearExpression(std::vector<int> _factors);
|
solidity::util::LinearExpression linearExpression(std::vector<int> _factors);
|
||||||
|
|
||||||
/// Queries LP solver and @returns solution.
|
/// Queries LP solver and @returns solution.
|
||||||
solution check();
|
solution checkLP();
|
||||||
|
|
||||||
|
/// Queries Z3 solver and @returns solution.
|
||||||
|
z3::check_result checkZ3();
|
||||||
|
|
||||||
/// Queries LP solver and @returns sat result as string.
|
/// Queries LP solver and @returns sat result as string.
|
||||||
std::string checkResult();
|
std::string checkLPResult();
|
||||||
|
|
||||||
|
/// Queries Z3 solver and @returns sat result as string.
|
||||||
|
std::string checkZ3Result();
|
||||||
|
|
||||||
|
/// @returns true if both the LP and the Z3 solver return an identical result on
|
||||||
|
/// @param _constraints, false otherwise.
|
||||||
|
bool differentialCheck(std::vector<std::pair<bool, std::vector<int>>> _constraints);
|
||||||
private:
|
private:
|
||||||
/// @returns LP result as string.
|
/// @returns LP result as string.
|
||||||
std::string lpResult(solidity::util::LPResult _result);
|
std::string lpResult(solidity::util::LPResult _result);
|
||||||
|
|
||||||
solidity::util::LPSolver m_solver;
|
/// @returns Z3 result as string.
|
||||||
solidity::util::SolvingState m_solvingState;
|
std::string z3Result(z3::check_result _result);
|
||||||
|
|
||||||
|
solidity::util::LPSolver m_lpSolver;
|
||||||
|
solidity::util::SolvingState m_lpSolvingState;
|
||||||
|
z3::context m_z3Ctx;
|
||||||
|
z3::solver m_z3Solver;
|
||||||
|
public:
|
||||||
|
std::string m_lpResult;
|
||||||
|
std::string m_z3Result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user