yul fuzzer: Add custom mutation routines

This commit is contained in:
Bhargava Shastry 2019-12-19 12:52:10 +01:00
parent e32bb74b30
commit ec56c785c1
3 changed files with 203 additions and 1 deletions

View File

@ -10,7 +10,11 @@ add_dependencies(ossfuzz
if (OSSFUZZ)
add_custom_target(ossfuzz_proto)
add_dependencies(ossfuzz_proto yul_proto_ossfuzz yul_proto_diff_ossfuzz)
add_dependencies(ossfuzz_proto
yul_proto_ossfuzz
yul_proto_diff_ossfuzz
yul_proto_diff_custom_mutate_ossfuzz
)
add_custom_target(ossfuzz_abiv2)
add_dependencies(ossfuzz_abiv2 abiv2_proto_ossfuzz)
@ -60,6 +64,22 @@ if (OSSFUZZ)
)
set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
add_executable(yul_proto_diff_custom_mutate_ossfuzz
yulProto_diff_ossfuzz.cpp
yulFuzzerCommon.cpp
protoToYul.cpp
yulProto.pb.cc
protomutators/YulProtoMutator.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
yulInterpreter
protobuf-mutator-libfuzzer.a
protobuf-mutator.a
protobuf.a
)
set_target_properties(yul_proto_diff_custom_mutate_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
add_executable(abiv2_proto_ossfuzz
../../EVMHost.cpp
abiV2ProtoFuzzer.cpp

View File

@ -0,0 +1,150 @@
#include <test/tools/ossfuzz/protomutators/YulProtoMutator.h>
#include <src/text_format.h>
#define DEBUG
using namespace yul::test::yul_fuzzer;
/// Invert condition of an if statement
static YulProtoMutator invertIfCondition(
IfStmt::descriptor(),
[](google::protobuf::Message* _message, unsigned int _seed)
{
IfStmt* ifStmt = static_cast<IfStmt*>(_message);
if (_seed % YulProtoMutator::s_mediumIP == 0)
{
if (ifStmt->has_cond())
{
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
std::cout << "YULMUTATOR: If condition inverted" << std::endl;
#endif
UnaryOp* notOp = new UnaryOp();
notOp->set_op(UnaryOp::NOT);
Expression *oldCond = ifStmt->release_cond();
notOp->set_allocated_operand(oldCond);
Expression *ifCond = new Expression();
ifCond->set_allocated_unop(notOp);
ifStmt->set_allocated_cond(ifCond);
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
#endif
}
}
}
);
/// Add break statement in body of a for-loop statement
static YulProtoMutator addBreak(
ForStmt::descriptor(),
[](google::protobuf::Message* _message, unsigned int _seed)
{
ForStmt* forStmt = static_cast<ForStmt*>(_message);
if (_seed % YulProtoMutator::s_mediumIP == 0)
{
if (forStmt->has_for_body())
{
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
std::cout << "YULMUTATOR: Break added" << std::endl;
#endif
BreakStmt* breakStmt = new BreakStmt();
Statement* statement = forStmt->mutable_for_body()->add_statements();
statement->clear_stmt_oneof();
statement->set_allocated_breakstmt(breakStmt);
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
#endif
}
}
}
);
/// Add break statement in body of a for-loop statement
static YulProtoMutator addContinue(
ForStmt::descriptor(),
[](google::protobuf::Message* _message, unsigned int _seed)
{
ForStmt* forStmt = static_cast<ForStmt*>(_message);
if (_seed % YulProtoMutator::s_mediumIP == 0)
{
if (forStmt->has_for_body())
{
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
std::cout << "YULMUTATOR: Continue added" << std::endl;
#endif
ContinueStmt* contStmt = new ContinueStmt();
Statement* statement = forStmt->mutable_for_body()->add_statements();
statement->clear_stmt_oneof();
statement->set_allocated_contstmt(contStmt);
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
#endif
}
}
}
);
/// Add declaration statement referencing mload(0)
static YulProtoMutator addMloadZero(
VarDecl::descriptor(),
[](google::protobuf::Message* _message, unsigned int _seed)
{
VarDecl* varDeclStmt = static_cast<VarDecl*>(_message);
if (_seed % YulProtoMutator::s_mediumIP == 0)
{
if (varDeclStmt->has_expr())
{
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
std::cout << "YULMUTATOR: mload added" << std::endl;
#endif
varDeclStmt->clear_expr();
Literal *zeroLit = new Literal();
zeroLit->set_intval(0);
Expression *consExpr = new Expression();
consExpr->set_allocated_cons(zeroLit);
UnaryOp *mloadOp = new UnaryOp();
mloadOp->set_op(UnaryOp::MLOAD);
mloadOp->set_allocated_operand(consExpr);
Expression *mloadExpr = new Expression();
mloadExpr->set_allocated_unop(mloadOp);
varDeclStmt->set_allocated_expr(mloadExpr);
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
#endif
}
}
}
);
/// Invert condition of a for statement
static YulProtoMutator invertForCondition(
ForStmt::descriptor(),
[](google::protobuf::Message* _message, unsigned int _seed)
{
ForStmt* forStmt = static_cast<ForStmt*>(_message);
if (_seed % YulProtoMutator::s_mediumIP == 0)
{
if (forStmt->has_for_cond())
{
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
std::cout << "YULMUTATOR: For condition inverted" << std::endl;
#endif
UnaryOp* notOp = new UnaryOp();
notOp->set_op(UnaryOp::NOT);
Expression *oldCond = forStmt->release_for_cond();
notOp->set_allocated_operand(oldCond);
Expression *forCond = new Expression();
forCond->set_allocated_unop(notOp);
forStmt->set_allocated_for_cond(forCond);
#ifdef DEBUG
// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl;
#endif
}
}
}
);

View File

@ -0,0 +1,32 @@
#pragma once
#include <test/tools/ossfuzz/yulProto.pb.h>
#include <src/libfuzzer/libfuzzer_macro.h>
namespace yul
{
namespace test
{
namespace yul_fuzzer
{
struct YulProtoMutator
{
YulProtoMutator(
google::protobuf::Descriptor const* _desc,
std::function<void(google::protobuf::Message*, unsigned int)> _callback
)
{
protobuf_mutator::libfuzzer::RegisterPostProcessor(_desc, _callback);
}
static constexpr unsigned s_lowIP = 41;
static constexpr unsigned s_mediumIP = 29;
static constexpr unsigned s_highIP = 17;
};
}
}
}