mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into breaking
This commit is contained in:
@@ -72,16 +72,16 @@ void FuzzerUtil::testCompilerJsonInterface(string const& _input, bool _optimize,
|
||||
runCompiler(jsonCompactPrint(config), _quiet);
|
||||
}
|
||||
|
||||
void FuzzerUtil::testCompiler(string const& _input, bool _optimize)
|
||||
void FuzzerUtil::testCompiler(StringMap const& _input, bool _optimize, unsigned _rand)
|
||||
{
|
||||
frontend::CompilerStack compiler;
|
||||
EVMVersion evmVersion = s_evmVersions[_input.size() % s_evmVersions.size()];
|
||||
EVMVersion evmVersion = s_evmVersions[_rand % s_evmVersions.size()];
|
||||
frontend::OptimiserSettings optimiserSettings;
|
||||
if (_optimize)
|
||||
optimiserSettings = frontend::OptimiserSettings::standard();
|
||||
else
|
||||
optimiserSettings = frontend::OptimiserSettings::minimal();
|
||||
compiler.setSources({{"", _input}});
|
||||
compiler.setSources(_input);
|
||||
compiler.setEVMVersion(evmVersion);
|
||||
compiler.setOptimiserSettings(optimiserSettings);
|
||||
try
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
|
||||
#include <libsolutil/Common.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
@@ -28,5 +31,9 @@ struct FuzzerUtil
|
||||
static void testCompilerJsonInterface(std::string const& _input, bool _optimize, bool _quiet);
|
||||
static void testConstantOptimizer(std::string const& _input, bool _quiet);
|
||||
static void testStandardCompiler(std::string const& _input, bool _quiet);
|
||||
static void testCompiler(std::string const& _input, bool _optimize);
|
||||
/// Compiles @param _input which is a map of input file name to source code
|
||||
/// string with optimisation turned on if @param _optimize is true
|
||||
/// (off otherwise) and a pseudo-random @param _rand that selects the EVM
|
||||
/// version to be compiled for.
|
||||
static void testCompiler(solidity::StringMap const& _input, bool _optimize, unsigned _rand);
|
||||
};
|
||||
|
||||
@@ -23,11 +23,11 @@ if (OSSFUZZ)
|
||||
endif()
|
||||
|
||||
if (OSSFUZZ)
|
||||
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp ../../TestCaseReader.cpp)
|
||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp ../../TestCaseReader.cpp)
|
||||
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
|
||||
#include <test/tools/fuzzer_common.h>
|
||||
|
||||
#include <test/TestCaseReader.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace solidity::frontend::test;
|
||||
using namespace std;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
||||
@@ -25,7 +30,17 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
||||
if (_size <= 600)
|
||||
{
|
||||
string input(reinterpret_cast<char const*>(_data), _size);
|
||||
FuzzerUtil::testCompiler(input, /*optimize=*/false);
|
||||
map<string, string> sourceCode;
|
||||
try
|
||||
{
|
||||
TestCaseReader t = TestCaseReader(std::istringstream(input));
|
||||
sourceCode = t.sources().sources;
|
||||
}
|
||||
catch (runtime_error const&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
FuzzerUtil::testCompiler(sourceCode, /*optimize=*/false, /*_rand=*/_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,29 @@
|
||||
|
||||
#include <test/tools/fuzzer_common.h>
|
||||
|
||||
#include <test/TestCaseReader.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace solidity::frontend::test;
|
||||
using namespace std;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(uint8_t const* _data, size_t _size)
|
||||
{
|
||||
if (_size <= 600)
|
||||
{
|
||||
string input(reinterpret_cast<char const *>(_data), _size);
|
||||
FuzzerUtil::testCompiler(input, /*optimize=*/true);
|
||||
string input(reinterpret_cast<char const*>(_data), _size);
|
||||
map<string, string> sourceCode;
|
||||
try
|
||||
{
|
||||
TestCaseReader t = TestCaseReader(std::istringstream(input));
|
||||
sourceCode = t.sources().sources;
|
||||
}
|
||||
catch (runtime_error const&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
FuzzerUtil::testCompiler(sourceCode, /*optimize=*/true, /*rand=*/_size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -97,15 +97,17 @@ DEFINE_PROTO_FUZZER(Program const& _input)
|
||||
EVMDialect::strictAssemblyForEVMObjects(version)
|
||||
);
|
||||
|
||||
if (termReason == yulFuzzerUtil::TerminationReason::StepLimitReached)
|
||||
if (
|
||||
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
|
||||
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached
|
||||
)
|
||||
return;
|
||||
|
||||
stack.optimize();
|
||||
termReason = yulFuzzerUtil::interpret(
|
||||
yulFuzzerUtil::interpret(
|
||||
os2,
|
||||
stack.parserResult()->code,
|
||||
EVMDialect::strictAssemblyForEVMObjects(version),
|
||||
(yul::test::yul_fuzzer::yulFuzzerUtil::maxSteps * 4)
|
||||
EVMDialect::strictAssemblyForEVMObjects(version)
|
||||
);
|
||||
|
||||
bool isTraceEq = (os1.str() == os2.str());
|
||||
|
||||
@@ -145,6 +145,11 @@ void Interpreter::operator()(ForLoop const& _forLoop)
|
||||
}
|
||||
while (evaluate(*_forLoop.condition) != 0)
|
||||
{
|
||||
// Increment step for each loop iteration for loops with
|
||||
// an empty body and post blocks to prevent a deadlock.
|
||||
if (_forLoop.body.statements.size() == 0 && _forLoop.post.statements.size() == 0)
|
||||
incrementStep();
|
||||
|
||||
m_state.controlFlowState = ControlFlowState::Default;
|
||||
(*this)(_forLoop.body);
|
||||
if (m_state.controlFlowState == ControlFlowState::Break || m_state.controlFlowState == ControlFlowState::Leave)
|
||||
@@ -176,12 +181,6 @@ void Interpreter::operator()(Leave const&)
|
||||
|
||||
void Interpreter::operator()(Block const& _block)
|
||||
{
|
||||
m_state.numSteps++;
|
||||
if (m_state.maxSteps > 0 && m_state.numSteps >= m_state.maxSteps)
|
||||
{
|
||||
m_state.trace.emplace_back("Interpreter execution step limit reached.");
|
||||
throw StepLimitReached();
|
||||
}
|
||||
enterScope(_block);
|
||||
// Register functions.
|
||||
for (auto const& statement: _block.statements)
|
||||
@@ -193,6 +192,7 @@ void Interpreter::operator()(Block const& _block)
|
||||
|
||||
for (auto const& statement: _block.statements)
|
||||
{
|
||||
incrementStep();
|
||||
visit(statement);
|
||||
if (m_state.controlFlowState != ControlFlowState::Default)
|
||||
break;
|
||||
@@ -235,6 +235,16 @@ void Interpreter::leaveScope()
|
||||
yulAssert(m_scope, "");
|
||||
}
|
||||
|
||||
void Interpreter::incrementStep()
|
||||
{
|
||||
m_state.numSteps++;
|
||||
if (m_state.maxSteps > 0 && m_state.numSteps >= m_state.maxSteps)
|
||||
{
|
||||
m_state.trace.emplace_back("Interpreter execution step limit reached.");
|
||||
throw StepLimitReached();
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionEvaluator::operator()(Literal const& _literal)
|
||||
{
|
||||
static YulString const trueString("true");
|
||||
|
||||
@@ -154,6 +154,10 @@ private:
|
||||
void enterScope(Block const& _block);
|
||||
void leaveScope();
|
||||
|
||||
/// Increment interpreter step count, throwing exception if step limit
|
||||
/// is reached.
|
||||
void incrementStep();
|
||||
|
||||
Dialect const& m_dialect;
|
||||
InterpreterState& m_state;
|
||||
/// Values of variables.
|
||||
|
||||
Reference in New Issue
Block a user