mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #5942 from bshastry/sol-protofuzzer
LibProtobuf Mutator (LPM) based fuzzer for yul subset
This commit is contained in:
commit
5ddf9e269f
@ -1,3 +1,4 @@
|
||||
link_directories(/src/LPM/src /src/LPM/src/libfuzzer /src/LPM/external.protobuf/lib)
|
||||
add_custom_target(ossfuzz)
|
||||
add_dependencies(ossfuzz
|
||||
solc_opt_ossfuzz
|
||||
@ -6,6 +7,9 @@ add_dependencies(ossfuzz
|
||||
strictasm_diff_ossfuzz
|
||||
)
|
||||
|
||||
add_custom_target(ossfuzz_proto)
|
||||
add_dependencies(ossfuzz_proto yul_proto_ossfuzz yul_proto_diff_ossfuzz)
|
||||
|
||||
#[[FuzzingEngine.a is provided by oss-fuzz's Dockerized build environment]]
|
||||
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm FuzzingEngine.a)
|
||||
@ -17,4 +21,21 @@ add_executable(const_opt_ossfuzz const_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
target_link_libraries(const_opt_ossfuzz PRIVATE libsolc evmasm FuzzingEngine.a)
|
||||
|
||||
add_executable(strictasm_diff_ossfuzz strictasm_diff_ossfuzz.cpp yulFuzzerCommon.cpp)
|
||||
target_link_libraries(strictasm_diff_ossfuzz PRIVATE libsolc evmasm yulInterpreter FuzzingEngine.a)
|
||||
target_link_libraries(strictasm_diff_ossfuzz PRIVATE libsolc evmasm yulInterpreter FuzzingEngine.a)
|
||||
|
||||
add_executable(yul_proto_ossfuzz yulProtoFuzzer.cpp protoToYul.cpp yulProto.pb.cc)
|
||||
target_include_directories(yul_proto_ossfuzz PRIVATE /src/libprotobuf-mutator /src/LPM/external.protobuf/include)
|
||||
target_link_libraries(yul_proto_ossfuzz PRIVATE yul evmasm
|
||||
protobuf-mutator-libfuzzer.a
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
FuzzingEngine.a)
|
||||
|
||||
add_executable(yul_proto_diff_ossfuzz yulProto_diff_ossfuzz.cpp yulFuzzerCommon.cpp protoToYul.cpp yulProto.pb.cc)
|
||||
target_include_directories(yul_proto_diff_ossfuzz PRIVATE /src/libprotobuf-mutator /src/LPM/external.protobuf/include)
|
||||
target_link_libraries(yul_proto_diff_ossfuzz PRIVATE yul evmasm
|
||||
yulInterpreter
|
||||
protobuf-mutator-libfuzzer.a
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
FuzzingEngine.a)
|
||||
|
242
test/tools/ossfuzz/protoToYul.cpp
Normal file
242
test/tools/ossfuzz/protoToYul.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
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/protoToYul.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace yul::test::yul_fuzzer;
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Literal const& _x)
|
||||
{
|
||||
return _os << "(" << _x.val() << ")";
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, VarRef const& _x)
|
||||
{
|
||||
return _os << "x_" << (static_cast<uint32_t>(_x.varnum()) % 10);
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Expression const& _x)
|
||||
{
|
||||
if (_x.has_varref())
|
||||
return _os << _x.varref();
|
||||
else if (_x.has_cons())
|
||||
return _os << _x.cons();
|
||||
else if (_x.has_binop())
|
||||
return _os << _x.binop();
|
||||
else if (_x.has_unop())
|
||||
return _os << _x.unop();
|
||||
return _os << "";
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, BinaryOp const& _x)
|
||||
{
|
||||
switch (_x.op())
|
||||
{
|
||||
case BinaryOp::ADD:
|
||||
_os << "add(";
|
||||
break;
|
||||
case BinaryOp::SUB:
|
||||
_os << "sub(";
|
||||
break;
|
||||
case BinaryOp::MUL:
|
||||
_os << "mul(";
|
||||
break;
|
||||
case BinaryOp::DIV:
|
||||
_os << "div(";
|
||||
break;
|
||||
case BinaryOp::MOD:
|
||||
_os << "mod(";
|
||||
break;
|
||||
case BinaryOp::XOR:
|
||||
_os << "xor(";
|
||||
break;
|
||||
case BinaryOp::AND:
|
||||
_os << "and(";
|
||||
break;
|
||||
case BinaryOp::OR:
|
||||
_os << "or(";
|
||||
break;
|
||||
case BinaryOp::EQ:
|
||||
_os << "eq(";
|
||||
break;
|
||||
case BinaryOp::LT:
|
||||
_os << "lt(";
|
||||
break;
|
||||
case BinaryOp::GT:
|
||||
_os << "gt(";
|
||||
break;
|
||||
}
|
||||
return _os << _x.left() << "," << _x.right() << ")";
|
||||
}
|
||||
|
||||
// New var numbering starts from x_10 until x_16
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, VarDecl const& _x)
|
||||
{
|
||||
_os << "let x_" << ((_x.id() % 7) + 10) << " := " << _x.expr() << "\n";
|
||||
return _os;
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, TypedVarDecl const& _x)
|
||||
{
|
||||
_os << "let x_" << ((_x.id() % 7) + 10);
|
||||
switch (_x.type())
|
||||
{
|
||||
case TypedVarDecl::BOOL:
|
||||
_os << ": bool := " << _x.expr() << " : bool\n";
|
||||
break;
|
||||
case TypedVarDecl::S8:
|
||||
_os << ": s8 := " << _x.expr() << " : s8\n";
|
||||
break;
|
||||
case TypedVarDecl::S32:
|
||||
_os << ": s32 := " << _x.expr() << " : s32\n";
|
||||
break;
|
||||
case TypedVarDecl::S64:
|
||||
_os << ": s64 := " << _x.expr() << " : s64\n";
|
||||
break;
|
||||
case TypedVarDecl::S128:
|
||||
_os << ": s128 := " << _x.expr() << " : s128\n";
|
||||
break;
|
||||
case TypedVarDecl::S256:
|
||||
_os << ": s256 := " << _x.expr() << " : s256\n";
|
||||
break;
|
||||
case TypedVarDecl::U8:
|
||||
_os << ": u8 := " << _x.expr() << " : u8\n";
|
||||
break;
|
||||
case TypedVarDecl::U32:
|
||||
_os << ": u32 := " << _x.expr() << " : u32\n";
|
||||
break;
|
||||
case TypedVarDecl::U64:
|
||||
_os << ": u64 := " << _x.expr() << " : u64\n";
|
||||
break;
|
||||
case TypedVarDecl::U128:
|
||||
_os << ": u128 := " << _x.expr() << " : u128\n";
|
||||
break;
|
||||
case TypedVarDecl::U256:
|
||||
_os << ": u256 := " << _x.expr() << " : u256\n";
|
||||
break;
|
||||
}
|
||||
return _os;
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, UnaryOp const& _x)
|
||||
{
|
||||
switch (_x.op())
|
||||
{
|
||||
case UnaryOp::NOT:
|
||||
_os << "not(";
|
||||
break;
|
||||
case UnaryOp::MLOAD:
|
||||
_os << "mload(";
|
||||
break;
|
||||
case UnaryOp::SLOAD:
|
||||
_os << "sload(";
|
||||
break;
|
||||
case UnaryOp::ISZERO:
|
||||
_os << "iszero(";
|
||||
break;
|
||||
}
|
||||
_os << _x.operand() << ")";
|
||||
return _os;
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, AssignmentStatement const& _x)
|
||||
{
|
||||
return _os << _x.ref_id() << " := " << _x.expr() << "\n";
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, IfStmt const& _x)
|
||||
{
|
||||
return _os <<
|
||||
"if " <<
|
||||
_x.cond() <<
|
||||
" " <<
|
||||
_x.if_body();
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, StoreFunc const& _x)
|
||||
{
|
||||
switch (_x.st())
|
||||
{
|
||||
case StoreFunc::MSTORE:
|
||||
_os << "mstore(" << _x.loc() << ", " << _x.val() << ")\n";
|
||||
break;
|
||||
case StoreFunc::SSTORE:
|
||||
_os << "sstore(" << _x.loc() << ", " << _x.val() << ")\n";
|
||||
break;
|
||||
}
|
||||
return _os;
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Statement const& _x)
|
||||
{
|
||||
if (_x.has_decl())
|
||||
return _os << _x.decl();
|
||||
else if (_x.has_assignment())
|
||||
return _os << _x.assignment();
|
||||
else if (_x.has_ifstmt())
|
||||
return _os << _x.ifstmt();
|
||||
else if (_x.has_storage_func())
|
||||
return _os << _x.storage_func();
|
||||
else if (_x.has_blockstmt())
|
||||
return _os << _x.blockstmt();
|
||||
return _os << "";
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Block const& _x)
|
||||
{
|
||||
if (_x.statements_size() > 0)
|
||||
{
|
||||
_os << "{\n";
|
||||
for (auto const& st: _x.statements())
|
||||
_os << st;
|
||||
_os << "}\n";
|
||||
|
||||
}
|
||||
return _os;
|
||||
}
|
||||
|
||||
ostream& yul::test::yul_fuzzer::operator<<(ostream& _os, Function const& _x)
|
||||
{
|
||||
_os << "{\n"
|
||||
<< "let a,b := foo(calldataload(0),calldataload(32),calldataload(64),calldataload(96),calldataload(128),"
|
||||
<< "calldataload(160),calldataload(192),calldataload(224))\n"
|
||||
<< "sstore(0, a)\n"
|
||||
<< "sstore(32, b)\n"
|
||||
<< "function foo(x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7) -> x_8, x_9\n"
|
||||
<< _x.statements()
|
||||
<< "}\n";
|
||||
return _os;
|
||||
}
|
||||
|
||||
string yul::test::yul_fuzzer::functionToString(Function const& _input)
|
||||
{
|
||||
ostringstream os;
|
||||
os << _input;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
string yul::test::yul_fuzzer::protoToYul(const uint8_t* _data, size_t _size)
|
||||
{
|
||||
Function message;
|
||||
if (!message.ParsePartialFromArray(_data, _size))
|
||||
return "#error invalid proto\n";
|
||||
return functionToString(message);
|
||||
}
|
51
test/tools/ossfuzz/protoToYul.h
Normal file
51
test/tools/ossfuzz/protoToYul.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
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 <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||
|
||||
namespace yul
|
||||
{
|
||||
namespace test
|
||||
{
|
||||
namespace yul_fuzzer
|
||||
{
|
||||
class Function;
|
||||
|
||||
std::string functionToString(Function const& input);
|
||||
std::string protoToYul(uint8_t const* data, size_t size);
|
||||
std::ostream& operator<<(std::ostream& _os, BinaryOp const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, Block const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, Literal const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, VarRef const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, Expression const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, BinaryOp const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, VarDecl const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, TypedVarDecl const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, UnaryOp const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, AssignmentStatement const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, IfStmt const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, StoreFunc const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, Statement const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, Block const& _x);
|
||||
std::ostream& operator<<(std::ostream& _os, Function const& _x);
|
||||
}
|
||||
}
|
||||
}
|
156
test/tools/ossfuzz/yulProto.proto
Normal file
156
test/tools/ossfuzz/yulProto.proto
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
// VariableDeclaration =
|
||||
// 'let' TypedIdentifierList ( ':=' Expression )?
|
||||
// TypedIdentifierList = Identifier ':' TypeName ( ',' Identifier ':' TypeName )*
|
||||
// Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]*
|
||||
// IdentifierList = Identifier ( ',' Identifier)*
|
||||
// TypeName = Identifier | BuiltinTypeName
|
||||
// BuiltinTypeName = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )
|
||||
message VarDecl {
|
||||
required int32 id = 1;
|
||||
required Expression expr = 3;
|
||||
}
|
||||
|
||||
message TypedVarDecl {
|
||||
enum TypeName {
|
||||
BOOL = 1;
|
||||
U8 = 2;
|
||||
U32 = 3;
|
||||
U64 = 4;
|
||||
U128 = 5;
|
||||
U256 = 6;
|
||||
S8 = 7;
|
||||
S32 = 8;
|
||||
S64 = 9;
|
||||
S128 = 10;
|
||||
S256 = 11;
|
||||
};
|
||||
required int32 id = 1;
|
||||
required TypeName type = 2;
|
||||
required Expression expr = 3;
|
||||
}
|
||||
|
||||
message VarRef {
|
||||
required int32 varnum = 1;
|
||||
}
|
||||
|
||||
message Literal {
|
||||
required int32 val = 1;
|
||||
}
|
||||
|
||||
message TypedLiteral {
|
||||
enum TypeName {
|
||||
BOOL = 1;
|
||||
U8 = 2;
|
||||
U32 = 3;
|
||||
U64 = 4;
|
||||
U128 = 5;
|
||||
U256 = 6;
|
||||
S8 = 7;
|
||||
S32 = 8;
|
||||
S64 = 9;
|
||||
S128 = 10;
|
||||
S256 = 11;
|
||||
};
|
||||
required int32 val = 1;
|
||||
required TypeName type = 2;
|
||||
}
|
||||
|
||||
message BinaryOp {
|
||||
enum BOp {
|
||||
ADD = 0;
|
||||
SUB = 1;
|
||||
MUL = 2;
|
||||
DIV = 3;
|
||||
MOD = 4;
|
||||
XOR = 5;
|
||||
AND = 6;
|
||||
OR = 7;
|
||||
EQ = 8;
|
||||
LT = 9;
|
||||
GT = 10;
|
||||
};
|
||||
required BOp op = 1;
|
||||
required Expression left = 2;
|
||||
required Expression right = 3;
|
||||
}
|
||||
|
||||
message UnaryOp {
|
||||
enum UOp {
|
||||
NOT = 0;
|
||||
MLOAD = 1;
|
||||
SLOAD = 2;
|
||||
ISZERO = 3;
|
||||
}
|
||||
required UOp op = 1;
|
||||
required Expression operand = 2;
|
||||
}
|
||||
|
||||
message StoreFunc {
|
||||
enum Storage {
|
||||
MSTORE = 0;
|
||||
SSTORE = 1;
|
||||
}
|
||||
required Expression loc = 1;
|
||||
required Expression val = 2;
|
||||
required Storage st = 3;
|
||||
}
|
||||
|
||||
message Expression {
|
||||
oneof expr_oneof {
|
||||
VarRef varref = 1;
|
||||
Literal cons = 2;
|
||||
BinaryOp binop = 3;
|
||||
UnaryOp unop = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message AssignmentStatement {
|
||||
required VarRef ref_id = 1;
|
||||
required Expression expr = 2;
|
||||
}
|
||||
|
||||
message IfStmt {
|
||||
required Expression cond = 1;
|
||||
required Block if_body = 2;
|
||||
}
|
||||
|
||||
// add for loop
|
||||
// TODO: add block and scope for if
|
||||
message Statement {
|
||||
oneof stmt_oneof {
|
||||
VarDecl decl = 1;
|
||||
AssignmentStatement assignment = 2;
|
||||
IfStmt ifstmt = 3;
|
||||
StoreFunc storage_func = 4;
|
||||
Block blockstmt = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message Block {
|
||||
repeated Statement statements = 1;
|
||||
}
|
||||
|
||||
message Function {
|
||||
required Block statements = 1;
|
||||
}
|
||||
|
||||
package yul.test.yul_fuzzer;
|
59
test/tools/ossfuzz/yulProtoFuzzer.cpp
Normal file
59
test/tools/ossfuzz/yulProtoFuzzer.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 <fstream>
|
||||
|
||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||
#include <test/tools/fuzzer_common.h>
|
||||
#include <test/tools/ossfuzz/protoToYul.h>
|
||||
#include <src/libfuzzer/libfuzzer_macro.h>
|
||||
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
|
||||
using namespace yul;
|
||||
using namespace yul::test::yul_fuzzer;
|
||||
using namespace std;
|
||||
|
||||
DEFINE_BINARY_PROTO_FUZZER(Function const& _input)
|
||||
{
|
||||
string yul_source = functionToString(_input);
|
||||
|
||||
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
||||
{
|
||||
// With libFuzzer binary run this to generate a YUL source file x.yul:
|
||||
// PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input
|
||||
ofstream of(dump_path);
|
||||
of.write(yul_source.data(), yul_source.size());
|
||||
}
|
||||
|
||||
// AssemblyStack entry point
|
||||
AssemblyStack stack(langutil::EVMVersion(), AssemblyStack::Language::StrictAssembly);
|
||||
|
||||
// Parse protobuf mutated YUL code
|
||||
if (!stack.parseAndAnalyze("source", yul_source))
|
||||
return;
|
||||
|
||||
yulAssert(stack.errors().empty(), "Parsed successfully but had errors.");
|
||||
|
||||
if (!stack.parserResult()->code || !stack.parserResult()->analysisInfo)
|
||||
return;
|
||||
|
||||
// Optimize
|
||||
stack.optimize();
|
||||
}
|
75
test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp
Normal file
75
test/tools/ossfuzz/yulProto_diff_ossfuzz.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
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 <fstream>
|
||||
|
||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||
#include <test/tools/fuzzer_common.h>
|
||||
#include <test/tools/ossfuzz/protoToYul.h>
|
||||
#include <src/libfuzzer/libfuzzer_macro.h>
|
||||
|
||||
#include <libyul/AssemblyStack.h>
|
||||
#include <liblangutil/EVMVersion.h>
|
||||
#include <libyul/Exceptions.h>
|
||||
|
||||
#include <test/tools/ossfuzz/yulFuzzerCommon.h>
|
||||
|
||||
using namespace yul;
|
||||
using namespace yul::test::yul_fuzzer;
|
||||
using namespace std;
|
||||
|
||||
using namespace langutil;
|
||||
using namespace dev;
|
||||
using namespace yul::test;
|
||||
|
||||
DEFINE_BINARY_PROTO_FUZZER(Function const& _input)
|
||||
{
|
||||
string yul_source = functionToString(_input);
|
||||
|
||||
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
||||
{
|
||||
// With libFuzzer binary run this to generate a YUL source file x.yul:
|
||||
// PROTO_FUZZER_DUMP_PATH=x.yul ./a.out proto-input
|
||||
ofstream of(dump_path);
|
||||
of.write(yul_source.data(), yul_source.size());
|
||||
}
|
||||
|
||||
// AssemblyStack entry point
|
||||
AssemblyStack stack(langutil::EVMVersion(), AssemblyStack::Language::StrictAssembly);
|
||||
|
||||
try
|
||||
{
|
||||
// Parse protobuf mutated YUL code
|
||||
if (!stack.parseAndAnalyze("source", yul_source) || !stack.parserResult()->code ||
|
||||
!stack.parserResult()->analysisInfo)
|
||||
return;
|
||||
}
|
||||
catch (Exception const&)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ostringstream os1;
|
||||
ostringstream os2;
|
||||
yulFuzzerUtil::interpret(os1, stack.parserResult()->code);
|
||||
stack.optimize();
|
||||
yulFuzzerUtil::interpret(os2, stack.parserResult()->code);
|
||||
|
||||
bool isTraceEq = (os1.str() == os2.str());
|
||||
yulAssert(isTraceEq, "Interpreted traces for optimized and unoptimized code differ.");
|
||||
return;
|
||||
}
|
Loading…
Reference in New Issue
Block a user