Fuzzer: Enable fine-grained yul optimizer fuzzing

This commit is contained in:
Bhargava Shastry 2020-07-02 12:23:45 +02:00
parent 24f0f3bb16
commit 3b3c64efe2
9 changed files with 599 additions and 10 deletions

View File

@ -87,7 +87,14 @@ if (OSSFUZZ)
set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
target_compile_options(yul_proto_ossfuzz PUBLIC ${COMPILE_OPTIONS} -Wno-sign-conversion)
add_executable(yul_proto_diff_ossfuzz yulProto_diff_ossfuzz.cpp yulFuzzerCommon.cpp protoToYul.cpp yulProto.pb.cc)
add_executable(
yul_proto_diff_ossfuzz
yulProto_diff_ossfuzz.cpp
yulFuzzerCommon.cpp
protoToYul.cpp
yulProto.pb.cc
YulOptimizerStepTest.cpp
)
target_include_directories(yul_proto_diff_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
target_link_libraries(yul_proto_diff_ossfuzz PRIVATE yul
yulInterpreter
@ -104,6 +111,7 @@ if (OSSFUZZ)
protoToYul.cpp
yulProto.pb.cc
protomutators/YulProtoMutator.cpp
YulOptimizerStepTest.cpp
)
target_include_directories(yul_proto_diff_custom_mutate_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
target_link_libraries(yul_proto_diff_custom_mutate_ossfuzz PRIVATE yul

View File

@ -0,0 +1,367 @@
/*
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/>.
*/
#include <test/tools/ossfuzz/YulOptimizerStepTest.h>
#include <test/libsolidity/util/SoltestErrors.h>
#include <libyul/optimiser/BlockFlattener.h>
#include <libyul/optimiser/VarDeclInitializer.h>
#include <libyul/optimiser/VarNameCleaner.h>
#include <libyul/optimiser/ControlFlowSimplifier.h>
#include <libyul/optimiser/DeadCodeEliminator.h>
#include <libyul/optimiser/Disambiguator.h>
#include <libyul/optimiser/CircularReferencesPruner.h>
#include <libyul/optimiser/ConditionalUnsimplifier.h>
#include <libyul/optimiser/ConditionalSimplifier.h>
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
#include <libyul/optimiser/EquivalentFunctionCombiner.h>
#include <libyul/optimiser/ExpressionSplitter.h>
#include <libyul/optimiser/FunctionGrouper.h>
#include <libyul/optimiser/FunctionHoister.h>
#include <libyul/optimiser/ExpressionInliner.h>
#include <libyul/optimiser/FullInliner.h>
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
#include <libyul/optimiser/ForLoopInitRewriter.h>
#include <libyul/optimiser/LoadResolver.h>
#include <libyul/optimiser/LoopInvariantCodeMotion.h>
#include <libyul/optimiser/MainFunction.h>
#include <libyul/optimiser/NameDisplacer.h>
#include <libyul/optimiser/Rematerialiser.h>
#include <libyul/optimiser/ExpressionSimplifier.h>
#include <libyul/optimiser/UnusedPruner.h>
#include <libyul/optimiser/ExpressionJoiner.h>
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/optimiser/SSAReverser.h>
#include <libyul/optimiser/SSATransform.h>
#include <libyul/optimiser/RedundantAssignEliminator.h>
#include <libyul/optimiser/StructuralSimplifier.h>
#include <libyul/optimiser/StackCompressor.h>
#include <libyul/optimiser/Suite.h>
#include <libyul/backends/evm/ConstantOptimiser.h>
#include <libyul/backends/evm/EVMDialect.h>
#include <libyul/backends/evm/EVMMetrics.h>
#include <libyul/backends/wasm/WordSizeTransform.h>
#include <libyul/AsmPrinter.h>
#include <libyul/AsmAnalysis.h>
#include <libyul/AssemblyStack.h>
#include <liblangutil/SourceReferenceFormatter.h>
#include <libsolidity/interface/OptimiserSettings.h>
#include <variant>
using namespace solidity;
using namespace solidity::util;
using namespace solidity::langutil;
using namespace solidity::yul;
using namespace solidity::yul::test;
using namespace solidity::frontend;
using namespace solidity::frontend::test;
using namespace std;
YulOptimizerStepTest::YulOptimizerStepTest(
shared_ptr<Object> _obj,
Dialect const& _dialect,
string const& _optimizerStep
)
{
m_object = _obj;
m_ast = m_object->code;
m_analysisInfo = m_object->analysisInfo;
m_dialect = &_dialect;
m_optimizerStep = _optimizerStep;
}
shared_ptr<Block> YulOptimizerStepTest::run()
{
soltestAssert(m_dialect, "Dialect not set.");
updateContext();
if (m_optimizerStep == "disambiguator")
disambiguate();
else if (m_optimizerStep == "nameDisplacer")
{
disambiguate();
NameDisplacer{
*m_nameDispenser,
{"illegal1"_yulstring, "illegal2"_yulstring, "illegal3"_yulstring, "illegal4"_yulstring, "illegal5"_yulstring}
}(*m_ast);
}
else if (m_optimizerStep == "blockFlattener")
{
disambiguate();
BlockFlattener::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "constantOptimiser")
{
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
ConstantOptimiser{dynamic_cast<EVMDialect const&>(*m_dialect), meter}(*m_ast);
}
else if (m_optimizerStep == "varDeclInitializer")
VarDeclInitializer::run(*m_context, *m_ast);
else if (m_optimizerStep == "varNameCleaner")
{
FunctionHoister::run(*m_context, *m_ast);
VarNameCleaner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "forLoopConditionIntoBody")
{
disambiguate();
ForLoopConditionIntoBody::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "forLoopInitRewriter")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "commonSubexpressionEliminator")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
CommonSubexpressionEliminator::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "conditionalUnsimplifier")
{
disambiguate();
ConditionalUnsimplifier::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "conditionalSimplifier")
{
disambiguate();
ConditionalSimplifier::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "expressionSplitter")
ExpressionSplitter::run(*m_context, *m_ast);
else if (m_optimizerStep == "expressionJoiner")
{
disambiguate();
ExpressionJoiner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "splitJoin")
{
disambiguate();
ExpressionSplitter::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "functionGrouper")
{
disambiguate();
FunctionGrouper::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "functionHoister")
{
disambiguate();
FunctionHoister::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "expressionInliner")
{
disambiguate();
ExpressionInliner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "fullInliner")
{
disambiguate();
FunctionHoister::run(*m_context, *m_ast);
FunctionGrouper::run(*m_context, *m_ast);
ExpressionSplitter::run(*m_context, *m_ast);
FullInliner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "mainFunction")
{
disambiguate();
FunctionGrouper::run(*m_context, *m_ast);
MainFunction::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "rematerialiser")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
Rematerialiser::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "expressionSimplifier")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
ExpressionSimplifier::run(*m_context, *m_ast);
ExpressionSimplifier::run(*m_context, *m_ast);
ExpressionSimplifier::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "fullSimplify")
{
disambiguate();
ExpressionSplitter::run(*m_context, *m_ast);
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
CommonSubexpressionEliminator::run(*m_context, *m_ast);
ExpressionSimplifier::run(*m_context, *m_ast);
UnusedPruner::run(*m_context, *m_ast);
CircularReferencesPruner::run(*m_context, *m_ast);
DeadCodeEliminator::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "unusedPruner")
{
disambiguate();
UnusedPruner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "circularReferencesPruner")
{
disambiguate();
FunctionHoister::run(*m_context, *m_ast);
CircularReferencesPruner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "deadCodeEliminator")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
DeadCodeEliminator::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "ssaTransform")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
SSATransform::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "redundantAssignEliminator")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
RedundantAssignEliminator::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "ssaPlusCleanup")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
SSATransform::run(*m_context, *m_ast);
RedundantAssignEliminator::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "loadResolver")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
ExpressionSplitter::run(*m_context, *m_ast);
CommonSubexpressionEliminator::run(*m_context, *m_ast);
ExpressionSimplifier::run(*m_context, *m_ast);
LoadResolver::run(*m_context, *m_ast);
UnusedPruner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
ExpressionJoiner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "loopInvariantCodeMotion")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
LoopInvariantCodeMotion::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "controlFlowSimplifier")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
ControlFlowSimplifier::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "structuralSimplifier")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
LiteralRematerialiser::run(*m_context, *m_ast);
StructuralSimplifier::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "equivalentFunctionCombiner")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
EquivalentFunctionCombiner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "ssaReverser")
{
disambiguate();
SSAReverser::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "ssaAndBack")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
// apply SSA
SSATransform::run(*m_context, *m_ast);
RedundantAssignEliminator::run(*m_context, *m_ast);
// reverse SSA
SSAReverser::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
CommonSubexpressionEliminator::run(*m_context, *m_ast);
UnusedPruner::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "stackCompressor")
{
disambiguate();
ForLoopInitRewriter::run(*m_context, *m_ast);
FunctionHoister::run(*m_context, *m_ast);
FunctionGrouper::run(*m_context, *m_ast);
size_t maxIterations = 16;
StackCompressor::run(*m_dialect, *m_object, true, maxIterations);
BlockFlattener::run(*m_context, *m_ast);
}
else if (m_optimizerStep == "wordSizeTransform")
{
disambiguate();
ExpressionSplitter::run(*m_context, *m_ast);
WordSizeTransform::run(*m_dialect, *m_dialect, *m_ast, *m_nameDispenser);
}
else if (m_optimizerStep == "fullSuite")
{
GasMeter meter(dynamic_cast<EVMDialect const&>(*m_dialect), false, 200);
OptimiserSuite::run(*m_dialect, &meter, *m_object, true, solidity::frontend::OptimiserSettings::DefaultYulOptimiserSteps);
}
else
solUnimplemented("Invalid optimization step");
#if 0
std::cout << AsmPrinter{*m_dialect}(*m_ast) << std::endl;
#endif
return m_ast;
}
void YulOptimizerStepTest::disambiguate()
{
*m_ast = std::get<Block>(Disambiguator(*m_dialect, *m_analysisInfo)(*m_ast));
m_analysisInfo.reset();
updateContext();
}
void YulOptimizerStepTest::updateContext()
{
m_nameDispenser = make_unique<NameDispenser>(*m_dialect, *m_ast, m_reservedIdentifiers);
m_context = make_unique<OptimiserStepContext>(OptimiserStepContext{
*m_dialect,
*m_nameDispenser,
m_reservedIdentifiers
});
}

View File

@ -0,0 +1,73 @@
/*
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/>.
*/
#pragma once
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/optimiser/NameDispenser.h>
#include <libyul/YulString.h>
#include <memory>
#include <set>
namespace solidity::langutil
{
class Scanner;
class Error;
using ErrorList = std::vector<std::shared_ptr<Error const>>;
class EVMVersion;
}
namespace solidity::yul
{
struct AsmAnalysisInfo;
struct Block;
struct Dialect;
struct Object;
}
namespace solidity::yul::test
{
class YulOptimizerStepTest
{
public:
explicit YulOptimizerStepTest(
std::shared_ptr<Object> _obj,
Dialect const& _dialect,
std::string const& _optimizerStep
);
std::shared_ptr<Block> run();
private:
void disambiguate();
void updateContext();
std::string m_optimizerStep;
Dialect const* m_dialect = nullptr;
std::set<YulString> m_reservedIdentifiers;
std::unique_ptr<NameDispenser> m_nameDispenser;
std::unique_ptr<OptimiserStepContext> m_context;
std::shared_ptr<Block> m_ast;
std::shared_ptr<AsmAnalysisInfo> m_analysisInfo;
std::shared_ptr<Object> m_object;
};
}

View File

@ -1905,6 +1905,87 @@ void ProtoConverter::buildObjectScopeTree(Object const& _x)
m_objectScope.emplace(objectName, node);
}
string ProtoConverter::optStepToString(Program_OptimizerStep const& _x)
{
switch (_x)
{
case Program_OptimizerStep_FULLSUITE:
return "fullSuite";
case Program_OptimizerStep_DISAMBIGUATOR:
return "disambiguator";
case Program_OptimizerStep_NAMEDISPLACER:
return "nameDisplacer";
case Program_OptimizerStep_BLOCKFLATTENER:
return "blockFlattener";
case Program_OptimizerStep_CONSTANTOPTIMISER:
return "constantOptimiser";
case Program_OptimizerStep_VARDECLINITIALIZER:
return "varDeclInitializer";
case Program_OptimizerStep_VARNAMECLEANER:
return "varNameCleaner";
case Program_OptimizerStep_FORLOOPCONDITIONINTOBODY:
return "forLoopConditionIntoBody";
case Program_OptimizerStep_FORLOOPINITREWRITER:
return "forLoopInitRewriter";
case Program_OptimizerStep_COMMONSUBEXPRESSIONELIMINATOR:
return "commonSubexpressionEliminator";
case Program_OptimizerStep_CONDITIONALUNSIMPLIFIER:
return "conditionalUnsimplifier";
case Program_OptimizerStep_CONDITIONALSIMPLIFIER:
return "conditionalSimplifier";
case Program_OptimizerStep_EXPRESSIONSPLITTER:
return "expressionSplitter";
case Program_OptimizerStep_EXPRESSIONJOINER:
return "expressionJoiner";
case Program_OptimizerStep_SPLITJOIN:
return "splitJoin";
case Program_OptimizerStep_FUNCTIONGROUPER:
return "functionGrouper";
case Program_OptimizerStep_FUNCTIONHOISTER:
return "functionHoister";
case Program_OptimizerStep_EXPRESSIONINLINER:
return "expressionInliner";
case Program_OptimizerStep_FULLINLINER:
return "fullInliner";
case Program_OptimizerStep_REMATERIALISER:
return "rematerialiser";
case Program_OptimizerStep_EXPRESSIONSIMPLIFIER:
return "expressionSimplifier";
case Program_OptimizerStep_FULLSIMPLIFY:
return "fullSimplify";
case Program_OptimizerStep_UNUSEDPRUNER:
return "unusedPruner";
case Program_OptimizerStep_CIRCULARREFERENCESPRUNER:
return "circularReferencesPruner";
case Program_OptimizerStep_DEADCODEELIMINATOR:
return "deadCodeEliminator";
case Program_OptimizerStep_SSATRANSFORM:
return "ssaTransform";
case Program_OptimizerStep_REDUNDANTASSIGNELIMINATOR:
return "redundantAssignEliminator";
case Program_OptimizerStep_SSAPLUSCLEANUP:
return "ssaPlusCleanup";
case Program_OptimizerStep_LOADRESOLVER:
return "loadResolver";
case Program_OptimizerStep_LOOPINVARIANTCODEMOTION:
return "loopInvariantCodeMotion";
case Program_OptimizerStep_CONTROLFLOWSIMPLIFIER:
return "controlFlowSimplifier";
case Program_OptimizerStep_STRUCTURALSIMPLIFIER:
return "structuralSimplifier";
case Program_OptimizerStep_EQUIVALENTFUNCTIONCOMBINER:
return "equivalentFunctionCombiner";
case Program_OptimizerStep_SSAREVERSER:
return "ssaReverser";
case Program_OptimizerStep_SSAANDBACK:
return "ssaAndBack";
case Program_OptimizerStep_STACKCOMPRESSION:
return "stackCompressor";
default:
return "fullSuite";
}
}
void ProtoConverter::visit(Program const& _x)
{
// Initialize input size
@ -1913,6 +1994,9 @@ void ProtoConverter::visit(Program const& _x)
// Record EVM Version
m_evmVersion = evmVersionMapping(_x.ver());
// Record optimizer step
m_optimizerStep = optStepToString(_x.step());
// Program is either a Yul object or a block of
// statements.
switch (_x.program_oneof_case())

View File

@ -65,6 +65,12 @@ public:
return m_evmVersion;
}
/// Returns optimizer step string
std::string optStepString()
{
return m_optimizerStep;
}
private:
void visit(BinaryOp const&);
@ -291,6 +297,9 @@ private:
/// enum of type Program_Version
solidity::langutil::EVMVersion evmVersionMapping(Program_Version const& _x);
/// Returns string representation of an optimization step.
std::string optStepToString(Program_OptimizerStep const& _x);
/// Returns a monotonically increasing counter that starts from zero.
unsigned counter()
{
@ -390,5 +399,7 @@ private:
bool m_forInitScopeExtEnabled;
/// Object that holds the targeted evm version specified by protobuf input
solidity::langutil::EVMVersion m_evmVersion;
/// Optimizer step
std::string m_optimizerStep;
};
}

View File

@ -63,7 +63,7 @@ yulFuzzerUtil::TerminationReason yulFuzzerUtil::interpret(
}
catch (ExpressionNestingLimitReached const&)
{
reason = TerminationReason::ExpresionNestingLimitReached;
reason = TerminationReason::ExpressionNestingLimitReached;
}
catch (ExplicitlyTerminated const&)
{

View File

@ -28,7 +28,7 @@ struct yulFuzzerUtil
ExplicitlyTerminated,
StepLimitReached,
TraceLimitReached,
ExpresionNestingLimitReached,
ExpressionNestingLimitReached,
None
};

View File

@ -410,11 +410,50 @@ message Program {
ISTANBUL = 6;
BERLIN = 7;
}
enum OptimizerStep {
FULLSUITE = 0;
DISAMBIGUATOR = 1;
NAMEDISPLACER = 2;
BLOCKFLATTENER = 3;
CONSTANTOPTIMISER = 4;
VARDECLINITIALIZER = 5;
VARNAMECLEANER = 6;
FORLOOPCONDITIONINTOBODY = 7;
FORLOOPINITREWRITER = 8;
COMMONSUBEXPRESSIONELIMINATOR = 9;
CONDITIONALUNSIMPLIFIER = 10;
CONDITIONALSIMPLIFIER = 11;
EXPRESSIONSPLITTER = 12;
EXPRESSIONJOINER = 13;
SPLITJOIN = 14;
FUNCTIONGROUPER = 15;
FUNCTIONHOISTER = 16;
EXPRESSIONINLINER = 17;
FULLINLINER = 18;
REMATERIALISER = 19;
EXPRESSIONSIMPLIFIER = 20;
FULLSIMPLIFY = 21;
UNUSEDPRUNER = 22;
CIRCULARREFERENCESPRUNER = 23;
DEADCODEELIMINATOR = 24;
SSATRANSFORM = 25;
REDUNDANTASSIGNELIMINATOR = 26;
SSAPLUSCLEANUP = 27;
LOADRESOLVER = 28;
LOOPINVARIANTCODEMOTION = 29;
CONTROLFLOWSIMPLIFIER = 30;
STRUCTURALSIMPLIFIER = 31;
EQUIVALENTFUNCTIONCOMBINER = 32;
SSAREVERSER = 33;
SSAANDBACK = 34;
STACKCOMPRESSION = 35;
}
oneof program_oneof {
Block block = 1;
Object obj = 2;
}
required Version ver = 3;
required OptimizerStep step = 4;
}
package solidity.yul.test.yul_fuzzer;

View File

@ -19,6 +19,7 @@
#include <fstream>
#include <test/tools/ossfuzz/yulProto.pb.h>
#include <test/tools/ossfuzz/YulOptimizerStepTest.h>
#include <test/tools/fuzzer_common.h>
#include <test/tools/ossfuzz/protoToYul.h>
#include <src/libfuzzer/libfuzzer_macro.h>
@ -59,6 +60,7 @@ DEFINE_PROTO_FUZZER(Program const& _input)
ProtoConverter converter;
string yul_source = converter.programToString(_input);
EVMVersion version = converter.version();
string optStep = converter.optStepString();
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
{
@ -91,24 +93,29 @@ DEFINE_PROTO_FUZZER(Program const& _input)
ostringstream os1;
ostringstream os2;
auto const& evmDialect = EVMDialect::strictAssemblyForEVMObjects(version);
yulFuzzerUtil::TerminationReason termReason = yulFuzzerUtil::interpret(
os1,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(version)
evmDialect
);
if (
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached ||
termReason == yulFuzzerUtil::TerminationReason::ExpresionNestingLimitReached
termReason == yulFuzzerUtil::TerminationReason::ExpressionNestingLimitReached ||
termReason == yulFuzzerUtil::TerminationReason::TraceLimitReached
)
return;
return;
stack.optimize();
YulOptimizerStepTest optimizerStepTest(
stack.parserResult(),
evmDialect,
optStep
);
termReason = yulFuzzerUtil::interpret(
os2,
stack.parserResult()->code,
EVMDialect::strictAssemblyForEVMObjects(version)
optimizerStepTest.run(),
evmDialect
);
if (
termReason == yulFuzzerUtil::TerminationReason::StepLimitReached ||