diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp index 4765ccd7f..b38d4e28d 100644 --- a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp @@ -51,7 +51,6 @@ static YulProtoMutator addBreak( #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; @@ -77,7 +76,6 @@ static YulProtoMutator addContinue( #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; @@ -147,4 +145,77 @@ static YulProtoMutator invertForCondition( } } } -); \ No newline at end of file +); + +/// Make for loop condition a function call that returns a single value +static YulProtoMutator funcCallForCondition( + ForStmt::descriptor(), + [](google::protobuf::Message* _message, unsigned int _seed) + { + ForStmt* forStmt = static_cast(_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: Function call in for condition" << std::endl; +#endif + forStmt->release_for_cond(); + FunctionCall *functionCall = new FunctionCall(); + functionCall->set_ret(FunctionCall::SINGLE); + functionCall->set_func_index(0); + Expression *forCondExpr = new Expression(); + forCondExpr->set_allocated_func_expr(functionCall); + forStmt->set_allocated_for_cond(forCondExpr); +#ifdef DEBUG +// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl; +#endif + } + } + } +); + +/// Define an identity function f(x) = x +static YulProtoMutator identityFunction( + Block::descriptor(), + [](google::protobuf::Message* _message, unsigned int _seed) + { + if (_seed % YulProtoMutator::s_mediumIP == 0) + { +#ifdef DEBUG +// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl; + std::cout << "YULMUTATOR: Identity function" << std::endl; +#endif + Block* blockStmt = static_cast(_message); + FunctionDef* functionDef = new FunctionDef(); + functionDef->set_num_input_params(1); + functionDef->set_num_output_params(1); + Block* functionBlock = new Block(); + AssignmentStatement* assignmentStatement = new AssignmentStatement(); + VarRef* varRef = new VarRef(); + varRef->set_varnum(1); + assignmentStatement->set_allocated_ref_id(varRef); + Expression* rhs = new Expression(); + VarRef* rhsRef = new VarRef(); + rhsRef->set_varnum(0); + rhs->set_allocated_varref(rhsRef); + assignmentStatement->set_allocated_expr(rhs); + Statement *stmt = functionBlock->add_statements(); + stmt->set_allocated_assignment(assignmentStatement); + functionDef->set_allocated_block(functionBlock); + Statement *funcdefStmt = blockStmt->add_statements(); + funcdefStmt->set_allocated_funcdef(functionDef); +#ifdef DEBUG +// std::cout << protobuf_mutator::SaveMessageAsText(*_message) << std::endl; +#endif + } + } +); + +Literal* YulProtoMutator::intLiteral(unsigned _value) +{ + Literal *lit = new Literal(); + lit->set_intval(_value); + return lit; +} \ No newline at end of file diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.h b/test/tools/ossfuzz/protomutators/YulProtoMutator.h index ed2798449..dbbf6c8b1 100644 --- a/test/tools/ossfuzz/protomutators/YulProtoMutator.h +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.h @@ -20,6 +20,15 @@ struct YulProtoMutator protobuf_mutator::libfuzzer::RegisterPostProcessor(_desc, _callback); } + /// Return an integer literal of the given value. + /// @param _value: Value of the integer literal + static Literal* intLiteral(unsigned _value); + + /// Return a variable reference + /// @param _index: Index of a variable in scope, 0 being the first + /// variable in scope. + static VarRef* varref(unsigned _index); + static constexpr unsigned s_lowIP = 41; static constexpr unsigned s_mediumIP = 29; static constexpr unsigned s_highIP = 17;