mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Create fuzzer solver interface and add constraint generator.
This commit is contained in:
parent
be9e2d320a
commit
11a903d330
@ -9,6 +9,7 @@ add_dependencies(ossfuzz
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (OSSFUZZ)
|
if (OSSFUZZ)
|
||||||
|
add_subdirectory(lpsolver)
|
||||||
add_custom_target(ossfuzz_proto)
|
add_custom_target(ossfuzz_proto)
|
||||||
add_dependencies(ossfuzz_proto
|
add_dependencies(ossfuzz_proto
|
||||||
sol_proto_ossfuzz
|
sol_proto_ossfuzz
|
||||||
@ -23,6 +24,13 @@ if (OSSFUZZ)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (OSSFUZZ)
|
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
|
add_executable(solc_ossfuzz
|
||||||
solc_ossfuzz.cpp
|
solc_ossfuzz.cpp
|
||||||
../fuzzer_common.cpp
|
../fuzzer_common.cpp
|
||||||
|
71
test/tools/ossfuzz/LPSolverCustomMutatorInterface.cpp
Normal file
71
test/tools/ossfuzz/LPSolverCustomMutatorInterface.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <test/tools/ossfuzz/LPSolverCustomMutatorInterface.h>
|
||||||
|
#include <test/tools/ossfuzz/lpsolver/ConstraintGenerator.h>
|
||||||
|
|
||||||
|
#include <liblangutil/Exceptions.h>
|
||||||
|
|
||||||
|
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<ConstraintGenerator>(_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;
|
||||||
|
}
|
46
test/tools/ossfuzz/LPSolverCustomMutatorInterface.h
Normal file
46
test/tools/ossfuzz/LPSolverCustomMutatorInterface.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/**
|
||||||
|
* Implements libFuzzer's custom mutator interface for LP Solver fuzzer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <test/tools/ossfuzz/lpsolver/ConstraintGenerator.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
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<ConstraintGenerator> generator;
|
||||||
|
};
|
||||||
|
}
|
32
test/tools/ossfuzz/LPSolverFuzzer.cpp
Normal file
32
test/tools/ossfuzz/LPSolverFuzzer.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
12
test/tools/ossfuzz/lpsolver/CMakeLists.txt
Normal file
12
test/tools/ossfuzz/lpsolver/CMakeLists.txt
Normal file
@ -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)
|
41
test/tools/ossfuzz/lpsolver/ConstraintGenerator.cpp
Normal file
41
test/tools/ossfuzz/lpsolver/ConstraintGenerator.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <test/tools/ossfuzz/lpsolver/ConstraintGenerator.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace solidity::test::fuzzer::lpsolver;
|
||||||
|
|
||||||
|
ConstraintGenerator::ConstraintGenerator(unsigned int _seed)
|
||||||
|
{
|
||||||
|
prng = make_shared<RandomEngine>(_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;
|
||||||
|
}
|
65
test/tools/ossfuzz/lpsolver/ConstraintGenerator.h
Normal file
65
test/tools/ossfuzz/lpsolver/ConstraintGenerator.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/*
|
||||||
|
* Generates an integer matrix of dimension n x m
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace solidity::test::fuzzer::lpsolver
|
||||||
|
{
|
||||||
|
|
||||||
|
using RandomEngine = std::mt19937;
|
||||||
|
using Distribution = std::uniform_int_distribution<int>;
|
||||||
|
|
||||||
|
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<int>::min(), std::numeric_limits<int>::max())(*prng);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<RandomEngine> 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
66
test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.cpp
Normal file
66
test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#include <test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
70
test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.h
Normal file
70
test/tools/ossfuzz/lpsolver/FuzzerSolverInterface.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/**
|
||||||
|
* Implements the Fuzzer-Solver interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libsolutil/LP.h>
|
||||||
|
#include <libsolutil/LinearExpression.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace solidity::test::fuzzer::lpsolver
|
||||||
|
{
|
||||||
|
|
||||||
|
using solution = std::pair<
|
||||||
|
solidity::util::LPResult,
|
||||||
|
std::map<std::string, solidity::util::rational>
|
||||||
|
>;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user