mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[Proto fuzzer] Add function calls, and multi variable declaration/assignment statements
This commit is contained in:
parent
c3a1c168d0
commit
495f7f9013
@ -33,7 +33,7 @@ target_link_libraries(strictasm_assembly_ossfuzz PRIVATE yul 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
|
||||
target_link_libraries(yul_proto_ossfuzz PRIVATE yul evmasm solidity
|
||||
protobuf-mutator-libfuzzer.a
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,8 @@
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
#include <test/tools/ossfuzz/yulProto.pb.h>
|
||||
#include <libdevcore/Common.h>
|
||||
@ -38,31 +40,34 @@ class ProtoConverter
|
||||
public:
|
||||
ProtoConverter()
|
||||
{
|
||||
// The hard-coded function template foo has 10 parameters that are already "live"
|
||||
m_numLiveVars = 10;
|
||||
m_numLiveVars = 0;
|
||||
m_numVarsPerScope.push(m_numLiveVars);
|
||||
m_numNestedForLoops = 0;
|
||||
m_inForScope.push(false);
|
||||
m_numFunctionSets = 0;
|
||||
}
|
||||
ProtoConverter(ProtoConverter const&) = delete;
|
||||
ProtoConverter(ProtoConverter&&) = delete;
|
||||
std::string functionToString(Function const& _input);
|
||||
std::string protoToYul(uint8_t const* _data, size_t _size);
|
||||
std::string programToString(Program const& _input);
|
||||
|
||||
private:
|
||||
void visit(BinaryOp const&);
|
||||
void visit(Block const&);
|
||||
void visit(SpecialBlock const&);
|
||||
void visit(Literal const&);
|
||||
void visit(VarRef const&);
|
||||
void visit(Expression const&);
|
||||
void visit(VarDecl const&);
|
||||
void visit(EmptyVarDecl const&);
|
||||
void visit(MultiVarDecl const&);
|
||||
void visit(TypedVarDecl const&);
|
||||
void visit(UnaryOp const&);
|
||||
void visit(AssignmentStatement const&);
|
||||
void visit(MultiAssignment const&);
|
||||
void visit(IfStmt const&);
|
||||
void visit(StoreFunc const&);
|
||||
void visit(Statement const&);
|
||||
void visit(Function const&);
|
||||
void visit(FunctionDefinition const&);
|
||||
void visit(ForStmt const&);
|
||||
void visit(CaseStmt const&);
|
||||
void visit(SwitchStmt const&);
|
||||
@ -75,19 +80,72 @@ private:
|
||||
void visit(RetRevStmt const&);
|
||||
void visit(SelfDestructStmt const&);
|
||||
void visit(TerminatingStmt const&);
|
||||
void visit(FunctionCallNoReturnVal const&);
|
||||
void visit(FunctionCallSingleReturnVal const&);
|
||||
void visit(FunctionCall const&);
|
||||
void visit(FunctionDefinitionNoReturnVal const&);
|
||||
void visit(FunctionDefinitionSingleReturnVal const&);
|
||||
void visit(FunctionDefinitionMultiReturnVal const&);
|
||||
void visit(Program const&);
|
||||
template <class T>
|
||||
void visit(google::protobuf::RepeatedPtrField<T> const& _repeated_field);
|
||||
void registerFunction(FunctionDefinition const&);
|
||||
|
||||
std::string createHex(std::string const& _hexBytes) const;
|
||||
std::string createAlphaNum(std::string const& _strBytes) const;
|
||||
bool isCaseLiteralUnique(Literal const&);
|
||||
enum class NumFunctionReturns
|
||||
{
|
||||
None,
|
||||
Single,
|
||||
Multiple
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void visitFunctionInputParams(T const&, unsigned);
|
||||
|
||||
template<class T>
|
||||
void createFunctionDefAndCall(T const&, unsigned, unsigned, NumFunctionReturns);
|
||||
std::string functionTypeToString(NumFunctionReturns _type);
|
||||
|
||||
template <class T>
|
||||
void registerFunction(T const& _x, NumFunctionReturns _type, unsigned _numOutputParams = 0)
|
||||
{
|
||||
unsigned numInputParams = _x.num_input_params() % modInputParams;
|
||||
switch (_type)
|
||||
{
|
||||
case NumFunctionReturns::None:
|
||||
m_functionVecNoReturnValue.push_back(numInputParams);
|
||||
break;
|
||||
case NumFunctionReturns::Single:
|
||||
m_functionVecSingleReturnValue.push_back(numInputParams);
|
||||
break;
|
||||
case NumFunctionReturns::Multiple:
|
||||
m_functionVecMultiReturnValue.push_back(std::make_pair(numInputParams, _numOutputParams));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostringstream m_output;
|
||||
std::stack<uint8_t> m_numVarsPerScope;
|
||||
int32_t m_numLiveVars;
|
||||
int32_t m_numNestedForLoops;
|
||||
// Number of live variables in inner scope of a function
|
||||
std::stack<unsigned> m_numVarsPerScope;
|
||||
// Number of live variables in function scope
|
||||
unsigned m_numLiveVars;
|
||||
// Number of nested for loops for loop index referencing
|
||||
unsigned m_numNestedForLoops;
|
||||
std::stack<bool> m_inForScope;
|
||||
// Set that is used for deduplicating switch case literals
|
||||
std::stack<std::set<dev::u256>> m_switchLiteralSetPerScope;
|
||||
// Total number of function sets. A function set contains one function of each type defined by
|
||||
// NumFunctionReturns
|
||||
unsigned m_numFunctionSets;
|
||||
// Look-up table per function type that holds the number of input (output) function parameters
|
||||
std::vector<unsigned> m_functionVecNoReturnValue;
|
||||
std::vector<unsigned> m_functionVecSingleReturnValue;
|
||||
std::vector<std::pair<unsigned, unsigned>> m_functionVecMultiReturnValue;
|
||||
// mod input/output parameters impose an upper bound on the number of input/output parameters a function may have.
|
||||
static unsigned constexpr modInputParams = 5;
|
||||
static unsigned constexpr modOutputParams = 5;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,56 @@ message VarDecl {
|
||||
required Expression expr = 1;
|
||||
}
|
||||
|
||||
message FunctionCallNoReturnVal {
|
||||
// Indexes a function that does not return anything
|
||||
required uint32 func_index = 1;
|
||||
required Expression in_param1 = 2;
|
||||
required Expression in_param2 = 3;
|
||||
required Expression in_param3 = 4;
|
||||
required Expression in_param4 = 5;
|
||||
}
|
||||
|
||||
// Used by Expression
|
||||
message FunctionCallSingleReturnVal {
|
||||
// Indexes a function that returns exactly one value
|
||||
required uint32 func_index = 1;
|
||||
required Expression in_param1 = 2;
|
||||
required Expression in_param2 = 3;
|
||||
required Expression in_param3 = 4;
|
||||
required Expression in_param4 = 5;
|
||||
}
|
||||
|
||||
message MultiVarDecl {
|
||||
// Indexes a function that returns more than one value
|
||||
required uint32 func_index = 1;
|
||||
required Expression in_param1 = 2;
|
||||
required Expression in_param2 = 3;
|
||||
required Expression in_param3 = 4;
|
||||
required Expression in_param4 = 5;
|
||||
}
|
||||
|
||||
message MultiAssignment {
|
||||
// Indexes a function that returns more than one value
|
||||
required uint32 func_index = 1;
|
||||
required Expression in_param1 = 2;
|
||||
required Expression in_param2 = 3;
|
||||
required Expression in_param3 = 4;
|
||||
required Expression in_param4 = 5;
|
||||
required VarRef out_param1 = 6;
|
||||
required VarRef out_param2 = 7;
|
||||
required VarRef out_param3 = 8;
|
||||
required VarRef out_param4 = 9;
|
||||
}
|
||||
|
||||
// We exclude function calls with single return value here and use them as expressions
|
||||
message FunctionCall {
|
||||
oneof functioncall_oneof {
|
||||
FunctionCallNoReturnVal call_zero = 1;
|
||||
MultiVarDecl call_multidecl = 2;
|
||||
MultiAssignment call_multiassign = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message TypedVarDecl {
|
||||
enum TypeName {
|
||||
BOOL = 1;
|
||||
@ -192,6 +242,7 @@ message Expression {
|
||||
UnaryOp unop = 4;
|
||||
TernaryOp top = 5;
|
||||
NullaryOp nop = 6;
|
||||
FunctionCallSingleReturnVal func_expr = 7;
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,21 +304,26 @@ message TerminatingStmt {
|
||||
}
|
||||
}
|
||||
|
||||
// Stub for a VarDecl without an Expression on the RHS
|
||||
message EmptyVarDecl {}
|
||||
|
||||
// TODO: Make Function definition a Statement
|
||||
message Statement {
|
||||
oneof stmt_oneof {
|
||||
VarDecl decl = 1;
|
||||
AssignmentStatement assignment = 2;
|
||||
IfStmt ifstmt = 3;
|
||||
StoreFunc storage_func = 4;
|
||||
Block blockstmt = 5;
|
||||
ForStmt forstmt = 6;
|
||||
SwitchStmt switchstmt = 7;
|
||||
BreakStmt breakstmt = 8;
|
||||
ContinueStmt contstmt = 9;
|
||||
LogFunc log_func = 10;
|
||||
CopyFunc copy_func = 11;
|
||||
ExtCodeCopy extcode_copy = 12;
|
||||
TerminatingStmt terminatestmt = 13;
|
||||
VarDecl decl = 1;
|
||||
AssignmentStatement assignment = 2;
|
||||
IfStmt ifstmt = 3;
|
||||
StoreFunc storage_func = 4;
|
||||
Block blockstmt = 5;
|
||||
ForStmt forstmt = 6;
|
||||
SwitchStmt switchstmt = 7;
|
||||
BreakStmt breakstmt = 8;
|
||||
ContinueStmt contstmt = 9;
|
||||
LogFunc log_func = 10;
|
||||
CopyFunc copy_func = 11;
|
||||
ExtCodeCopy extcode_copy = 12;
|
||||
TerminatingStmt terminatestmt = 13;
|
||||
FunctionCall functioncall = 14;
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,8 +331,39 @@ message Block {
|
||||
repeated Statement statements = 1;
|
||||
}
|
||||
|
||||
message Function {
|
||||
required Block statements = 1;
|
||||
// Identical to Block with the addition of an empty var right at the top
|
||||
// Used by FunctionDefinitionNoReturnVal only.
|
||||
message SpecialBlock {
|
||||
required EmptyVarDecl var = 1;
|
||||
repeated Statement statements = 2;
|
||||
}
|
||||
|
||||
// This ensures that proto mutator generates at least one of each type if it creates at least 1 functiondef message.
|
||||
message FunctionDefinition {
|
||||
required FunctionDefinitionNoReturnVal fd_zero = 1;
|
||||
required FunctionDefinitionSingleReturnVal fd_one = 2;
|
||||
required FunctionDefinitionMultiReturnVal fd_multi = 3;
|
||||
}
|
||||
|
||||
// Since this function can have 0 parameters, we hoist an empty var decl at the top via SpecialBlock.
|
||||
message FunctionDefinitionNoReturnVal {
|
||||
required uint32 num_input_params = 1;
|
||||
required SpecialBlock statements = 2;
|
||||
}
|
||||
|
||||
message FunctionDefinitionSingleReturnVal {
|
||||
required uint32 num_input_params = 1;
|
||||
required Block statements = 2;
|
||||
}
|
||||
|
||||
message FunctionDefinitionMultiReturnVal {
|
||||
required uint32 num_input_params = 1;
|
||||
required uint32 num_output_params = 2;
|
||||
required Block statements = 3;
|
||||
}
|
||||
|
||||
message Program {
|
||||
repeated FunctionDefinition funcs = 1;
|
||||
}
|
||||
|
||||
package yul.test.yul_fuzzer;
|
||||
|
@ -30,12 +30,10 @@ using namespace yul;
|
||||
using namespace yul::test::yul_fuzzer;
|
||||
using namespace std;
|
||||
|
||||
DEFINE_PROTO_FUZZER(Function const& _input)
|
||||
DEFINE_PROTO_FUZZER(Program const& _input)
|
||||
{
|
||||
ProtoConverter converter;
|
||||
string yul_source = converter.functionToString(_input);
|
||||
if (yul_source.size() > 600)
|
||||
return;
|
||||
string yul_source = converter.programToString(_input);
|
||||
|
||||
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
||||
{
|
||||
@ -45,6 +43,9 @@ DEFINE_PROTO_FUZZER(Function const& _input)
|
||||
of.write(yul_source.data(), yul_source.size());
|
||||
}
|
||||
|
||||
if (yul_source.size() > 1200)
|
||||
return;
|
||||
|
||||
// AssemblyStack entry point
|
||||
AssemblyStack stack(
|
||||
langutil::EVMVersion(),
|
||||
|
@ -37,12 +37,10 @@ using namespace langutil;
|
||||
using namespace dev;
|
||||
using namespace yul::test;
|
||||
|
||||
DEFINE_PROTO_FUZZER(Function const& _input)
|
||||
DEFINE_PROTO_FUZZER(Program const& _input)
|
||||
{
|
||||
ProtoConverter converter;
|
||||
string yul_source = converter.functionToString(_input);
|
||||
if (yul_source.size() > 600)
|
||||
return;
|
||||
string yul_source = converter.programToString(_input);
|
||||
|
||||
if (const char* dump_path = getenv("PROTO_FUZZER_DUMP_PATH"))
|
||||
{
|
||||
@ -52,6 +50,9 @@ DEFINE_PROTO_FUZZER(Function const& _input)
|
||||
of.write(yul_source.data(), yul_source.size());
|
||||
}
|
||||
|
||||
if (yul_source.size() > 1200)
|
||||
return;
|
||||
|
||||
// AssemblyStack entry point
|
||||
AssemblyStack stack(
|
||||
langutil::EVMVersion(),
|
||||
|
Loading…
Reference in New Issue
Block a user