diff --git a/test/tools/ossfuzz/Generators.h b/test/tools/ossfuzz/Generators.h index 4fd3026ea..56dcfdc99 100644 --- a/test/tools/ossfuzz/Generators.h +++ b/test/tools/ossfuzz/Generators.h @@ -52,4 +52,5 @@ MACRO(PragmaGenerator) SEP \ MACRO(SourceUnitGenerator) SEP \ MACRO(StatementGenerator) SEP \ - MACRO(TestCaseGenerator) ENDSEP + MACRO(TestCaseGenerator) SEP \ + MACRO(WhileStmtGenerator) ENDSEP diff --git a/test/tools/ossfuzz/SolidityGenerator.cpp b/test/tools/ossfuzz/SolidityGenerator.cpp index 54ebe5aeb..ac466380c 100644 --- a/test/tools/ossfuzz/SolidityGenerator.cpp +++ b/test/tools/ossfuzz/SolidityGenerator.cpp @@ -500,6 +500,36 @@ string IfStmtGenerator::visit() return ifStmt.str(); } +void WhileStmtGenerator::setup() +{ + set> dependsOn = { + {mutator->generator(), 1}, + }; + addGenerators(std::move(dependsOn)); +} + +string WhileStmtGenerator::visit() +{ + ostringstream whileStmt; + ExpressionGenerator exprGen{state}; + auto boolType = make_shared(); + pair boolTypeName = {boolType, {}}; + auto expression = exprGen.rLValueOrLiteral(boolTypeName); + solAssert(expression.has_value(), ""); + whileStmt << indentation() + << "while (" + << expression.value().second + << ")\n"; + // Make sure block stmt generator does not output an unchecked block + mutator->generator()->unchecked(false); + ostringstream whileBlock; + whileBlock << visitChildren(); + if (whileBlock.str().empty()) + whileBlock << indentation() << "{ }\n"; + whileStmt << whileBlock.str(); + return whileStmt.str(); +} + void StatementGenerator::setup() { set> dependsOn = { @@ -508,6 +538,7 @@ void StatementGenerator::setup() {mutator->generator(), 1}, {mutator->generator(), 1}, {mutator->generator(), 2}, + {mutator->generator(), 1} }; addGenerators(std::move(dependsOn)); } diff --git a/test/tools/ossfuzz/SolidityGenerator.h b/test/tools/ossfuzz/SolidityGenerator.h index 912c35569..33964ee1f 100644 --- a/test/tools/ossfuzz/SolidityGenerator.h +++ b/test/tools/ossfuzz/SolidityGenerator.h @@ -82,7 +82,7 @@ struct UniformRandomDistribution /// uniformly at random. [[nodiscard]] size_t distributionOneToN(size_t _n) const { - solAssert(_n > 0, ""); + solAssert(_n >= 1, ""); return Distribution(1, _n)(*randomEngine); } /// @returns true with a probability of 1/(@param _n), false otherwise. @@ -1094,7 +1094,17 @@ public: private: std::string conditionalStmt(Condition _cond); static constexpr size_t s_maxConditionalStmts = 5; +}; +class WhileStmtGenerator: public GeneratorBase +{ +public: + explicit WhileStmtGenerator(SolidityGenerator* _mutator): + GeneratorBase(std::move(_mutator)) + {} + void setup() override; + std::string visit() override; + std::string name() override { return "While statement generator"; } }; class AssignmentStmtGenerator: public GeneratorBase @@ -1175,7 +1185,7 @@ private: bool m_unchecked; bool m_inUnchecked; static constexpr unsigned s_maxStatements = 4; - static constexpr unsigned s_maxNestingDepth = 10; + static constexpr unsigned s_maxNestingDepth = 4; static constexpr size_t s_uncheckedInvProb = 13; };