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_custom_target(ossfuzz)
|
||||||
add_dependencies(ossfuzz
|
add_dependencies(ossfuzz
|
||||||
solc_opt_ossfuzz
|
solc_opt_ossfuzz
|
||||||
@ -6,6 +7,9 @@ add_dependencies(ossfuzz
|
|||||||
strictasm_diff_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]]
|
#[[FuzzingEngine.a is provided by oss-fuzz's Dockerized build environment]]
|
||||||
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm FuzzingEngine.a)
|
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)
|
target_link_libraries(const_opt_ossfuzz PRIVATE libsolc evmasm FuzzingEngine.a)
|
||||||
|
|
||||||
add_executable(strictasm_diff_ossfuzz strictasm_diff_ossfuzz.cpp yulFuzzerCommon.cpp)
|
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