From d56dfcf7503485538c19947560aaab81b92e5ca4 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Thu, 6 May 2021 13:25:32 +0200 Subject: [PATCH] Introduce assignment operations. --- test/tools/ossfuzz/SolidityGenerator.cpp | 132 ++++++++++++++++++++--- test/tools/ossfuzz/SolidityGenerator.h | 24 ++++- 2 files changed, 140 insertions(+), 16 deletions(-) diff --git a/test/tools/ossfuzz/SolidityGenerator.cpp b/test/tools/ossfuzz/SolidityGenerator.cpp index c5dd2e4fc..a8ff093cc 100644 --- a/test/tools/ossfuzz/SolidityGenerator.cpp +++ b/test/tools/ossfuzz/SolidityGenerator.cpp @@ -286,16 +286,128 @@ string FunctionState::params(Params _p) return "(" + boost::algorithm::join(params, ",") + ")"; } +AssignmentStmtGenerator::AssignOp AssignmentStmtGenerator::assignOp(SolidityTypePtr _type) +{ + enum Type + { + SIGNEDINTEGER = 1, + UNSIGNEDINTEGER, + BOOL, + FIXEDBYTES, + BYTES, + FUNCTION, + CONTRACT, + ADDRESS + }; + static map> assignOpLookUp = { + {SIGNEDINTEGER, { + AssignOp::ASSIGN, + AssignOp::ASSIGNBITOR, + AssignOp::ASSIGNBITXOR, + AssignOp::ASSIGNBITAND, + AssignOp::ASSIGNADD, + AssignOp::ASSIGNSUB, + AssignOp::ASSIGNMUL, + AssignOp::ASSIGNDIV, + AssignOp::ASSIGNMOD + }}, + {UNSIGNEDINTEGER, { + AssignOp::ASSIGN, + AssignOp::ASSIGNBITOR, + AssignOp::ASSIGNBITXOR, + AssignOp::ASSIGNBITAND, + AssignOp::ASSIGNSHL, + AssignOp::ASSIGNSAR, + AssignOp::ASSIGNSHR, + AssignOp::ASSIGNADD, + AssignOp::ASSIGNSUB, + AssignOp::ASSIGNMUL, + AssignOp::ASSIGNDIV, + AssignOp::ASSIGNMOD + }}, + {FIXEDBYTES, { + AssignOp::ASSIGN, + AssignOp::ASSIGNBITOR, + AssignOp::ASSIGNBITXOR, + AssignOp::ASSIGNBITAND + }}, + {BOOL, {AssignOp::ASSIGN}}, + {BYTES, {AssignOp::ASSIGN}}, + {FUNCTION, {AssignOp::ASSIGN}}, + {CONTRACT, {AssignOp::ASSIGN}}, + {ADDRESS, {AssignOp::ASSIGN}} + }; + vector possibleOps; + if (holds_alternative>(_type)) + { + auto t = get>(_type); + if (t->signedType) + possibleOps = assignOpLookUp[SIGNEDINTEGER]; + else + possibleOps = assignOpLookUp[UNSIGNEDINTEGER]; + } + else if (holds_alternative>(_type)) + { + possibleOps = assignOpLookUp[FIXEDBYTES]; + } + else if (holds_alternative>(_type) || + holds_alternative>(_type) || + holds_alternative>(_type) || + holds_alternative>(_type) || + holds_alternative>(_type) + ) + { + return AssignOp::ASSIGN; + } + else + solAssert(false, ""); + + return possibleOps[uRandDist->distributionOneToN(possibleOps.size()) - 1]; +} + +string AssignmentStmtGenerator::assignOp(AssignOp _op) +{ + switch (_op) + { + case AssignOp::ASSIGN: + return " = "; + case AssignOp::ASSIGNBITOR: + return " |= "; + case AssignOp::ASSIGNBITXOR: + return " ^= "; + case AssignOp::ASSIGNBITAND: + return " &= "; + case AssignOp::ASSIGNSHL: + return " <<= "; + case AssignOp::ASSIGNSAR: + case AssignOp::ASSIGNSHR: + return " >>= "; + case AssignOp::ASSIGNADD: + return " += "; + case AssignOp::ASSIGNSUB: + return " -= "; + case AssignOp::ASSIGNMUL: + return " *= "; + case AssignOp::ASSIGNDIV: + return " /= "; + case AssignOp::ASSIGNMOD: + return " %= "; + default: + solAssert(false, ""); + } +} + string AssignmentStmtGenerator::visit() { ExpressionGenerator exprGen{state}; - auto lhs = exprGen.expression(); + auto lhs = exprGen.randomLValueExpression(); if (!lhs.has_value()) return "\n"; auto rhs = exprGen.expression(lhs.value()); if (!rhs.has_value()) return "\n"; - return indentation() + lhs.value().second + " = " + rhs.value().second + ";\n"; + auto operation = assignOp(lhs.value().first); + return indentation() + lhs.value().second + assignOp(operation) + rhs.value().second + ";\n"; } void StatementGenerator::setup() @@ -425,7 +537,7 @@ void FunctionGenerator::endVisit() mutator->generator()->resetNestingDepth(); } -pair ExpressionGenerator::randomLValueExpression() +optional> ExpressionGenerator::randomLValueExpression() { LValueExpr exprType = static_cast( state->uRandDist->distributionOneToN(static_cast(LValueExpr::TYPEMAX) - 1) @@ -444,7 +556,10 @@ pair ExpressionGenerator::randomLValueExpression() liveVariables += scope->variables | ranges::views::transform([](auto& _item) { return _item; }) | ranges::to>>(); - return liveVariables[state->uRandDist->distributionOneToN(liveVariables.size()) - 1]; + if (liveVariables.empty()) + return nullopt; + else + return liveVariables[state->uRandDist->distributionOneToN(liveVariables.size()) - 1]; } default: solAssert(false, ""); @@ -476,15 +591,6 @@ optional> ExpressionGenerator::lValueExpression( return liveTypedVariables[state->uRandDist->distributionOneToN(liveTypedVariables.size()) - 1]; } -optional> ExpressionGenerator::expression() -{ - auto currentFunctionState = state->currentFunctionState(); - // TODO: Remove this barrier once we support more expression types. - if (currentFunctionState->inputs.empty() && currentFunctionState->outputs.empty()) - return nullopt; - return randomLValueExpression(); -} - pair ExpressionGenerator::literal(SolidityTypePtr _type) { string literalValue = visit(LiteralGenerator{state}, _type); diff --git a/test/tools/ossfuzz/SolidityGenerator.h b/test/tools/ossfuzz/SolidityGenerator.h index 7027b3812..d738592f7 100644 --- a/test/tools/ossfuzz/SolidityGenerator.h +++ b/test/tools/ossfuzz/SolidityGenerator.h @@ -755,8 +755,7 @@ struct ExpressionGenerator std::pair _typeName ); std::pair literal(SolidityTypePtr _type); - std::optional> expression(); - std::pair randomLValueExpression(); + std::optional> randomLValueExpression(); std::optional> lValueExpression( std::pair _typeName ); @@ -952,11 +951,30 @@ private: class AssignmentStmtGenerator: public GeneratorBase { public: + enum class AssignOp: size_t + { + ASSIGN = 1, + ASSIGNBITOR, + ASSIGNBITXOR, + ASSIGNBITAND, + ASSIGNSHL, + ASSIGNSAR, + ASSIGNSHR, + ASSIGNADD, + ASSIGNSUB, + ASSIGNMUL, + ASSIGNDIV, + ASSIGNMOD, + ASSIGNMAX + }; explicit AssignmentStmtGenerator(std::shared_ptr _mutator): GeneratorBase(std::move(_mutator)) {} std::string visit() override; std::string name() override { return "Assignment statement generator"; } +private: + AssignOp assignOp(SolidityTypePtr _type); + std::string assignOp(AssignOp _op); }; class BlockStmtGenerator: public GeneratorBase @@ -1008,7 +1026,7 @@ private: bool m_unchecked; bool m_inUnchecked; static constexpr unsigned s_maxStatements = 4; - static constexpr unsigned s_maxNestingDepth = 3; + static constexpr unsigned s_maxNestingDepth = 1; static constexpr size_t s_uncheckedInvProb = 13; };