diff --git a/test/tools/ossfuzz/SolidityGenerator.cpp b/test/tools/ossfuzz/SolidityGenerator.cpp index 471430a3d..f5975b64e 100644 --- a/test/tools/ossfuzz/SolidityGenerator.cpp +++ b/test/tools/ossfuzz/SolidityGenerator.cpp @@ -24,13 +24,12 @@ using namespace solidity::test::fuzzer; using namespace solidity::util; using namespace std; -using PrngUtil = solidity::test::fuzzer::GenerationProbability; GeneratorBase::GeneratorBase(std::shared_ptr _mutator) { mutator = std::move(_mutator); - rand = mutator->randomEngine(); state = mutator->testState(); + uRandDist = mutator->uniformRandomDist(); } string GeneratorBase::visitChildren() @@ -38,9 +37,9 @@ string GeneratorBase::visitChildren() ostringstream os; // Randomise visit order vector randomisedChildren; - for (auto child: generators) + for (auto const& child: generators) randomisedChildren.push_back(child); - shuffle(randomisedChildren.begin(), randomisedChildren.end(), *rand); + shuffle(randomisedChildren.begin(), randomisedChildren.end(), *uRandDist->randomEngine); for (auto child: randomisedChildren) os << std::visit(GenericVisitor{ [&](auto const& _item) { return _item->generate(); } @@ -52,7 +51,7 @@ string TestState::randomPath(set const& _sourceUnitPaths) const { auto it = _sourceUnitPaths.begin(); /// Advance iterator by n where 0 <= n <= sourceUnitPaths.size() - 1 - size_t increment = PrngUtil{}.distributionOneToN(_sourceUnitPaths.size(), rand) - 1; + size_t increment = uRandDist->distributionOneToN(_sourceUnitPaths.size()) - 1; solAssert( increment >= 0 && increment < _sourceUnitPaths.size(), "Solc custom mutator: Invalid increment" @@ -104,7 +103,7 @@ void TestCaseGenerator::setup() string TestCaseGenerator::visit() { ostringstream os; - for (unsigned i = 0; i < PrngUtil{}.distributionOneToN(s_maxSourceUnits, rand); i++) + for (unsigned i = 0; i < uRandDist->distributionOneToN(s_maxSourceUnits); i++) { string sourcePath = path(); os << "\n" @@ -140,7 +139,7 @@ string PragmaGenerator::visit() )"; // Choose equally at random from coder v1 and v2 string abiPragma = "pragma abicoder v" + - to_string(PrngUtil{}.distributionOneToN(2, rand)) + + to_string(uRandDist->distributionOneToN(2)) + ";\n"; return preamble + abiPragma; } @@ -157,7 +156,7 @@ string ImportGenerator::visit() // there is one source unit present in test. if (state->size() == 1) { - if (PrngUtil{}.probable(s_selfImportInvProb, rand)) + if (uRandDist->probable(s_selfImportInvProb)) os << "import " << "\"" << state->randomPath() @@ -186,9 +185,9 @@ shared_ptr SolidityGenerator::generator() SolidityGenerator::SolidityGenerator(unsigned _seed) { - m_rand = make_shared(_seed); m_generators = {}; - m_state = make_shared(m_rand); + m_urd = make_shared(make_unique(_seed)); + m_state = make_shared(m_urd); } template diff --git a/test/tools/ossfuzz/SolidityGenerator.h b/test/tools/ossfuzz/SolidityGenerator.h index 195cd4140..6b8a535f8 100644 --- a/test/tools/ossfuzz/SolidityGenerator.h +++ b/test/tools/ossfuzz/SolidityGenerator.h @@ -58,29 +58,34 @@ GENERATORLIST(VARIANTOFGENERATOR, COMMA(), ) using RandomEngine = std::mt19937_64; using Distribution = std::uniform_int_distribution; -struct GenerationProbability +struct UniformRandomDistribution { + explicit UniformRandomDistribution(std::unique_ptr _randomEngine): + randomEngine(std::move(_randomEngine)) + {} + /// @returns an unsigned integer in the range [1, @param _n] chosen /// uniformly at random. - static size_t distributionOneToN(size_t _n, std::shared_ptr const& _rand) + [[nodiscard]] size_t distributionOneToN(size_t _n) const { - return Distribution(1, _n)(*_rand); + return Distribution(1, _n)(*randomEngine); } /// @returns true with a probability of 1/(@param _n), false otherwise. /// @param _n must be non zero. - static bool probable(size_t _n, std::shared_ptr const& _rand) + [[nodiscard]] bool probable(size_t _n) const { solAssert(_n > 0, ""); - return distributionOneToN(_n, _rand) == 1; + return distributionOneToN(_n) == 1; } + std::unique_ptr randomEngine; }; struct TestState { - explicit TestState(std::shared_ptr _rand): + explicit TestState(std::shared_ptr _urd): sourceUnitPaths({}), currentSourceUnitPath({}), - rand(std::move(_rand)) + uRandDist(std::move(_urd)) {} /// Adds @param _path to @name sourceUnitPaths updates /// @name currentSourceUnitPath. @@ -95,25 +100,25 @@ struct TestState { return sourceUnitPaths.empty(); } - /// Returns the number of items in @name sourceUnitPaths. + /// @returns the number of items in @name sourceUnitPaths. [[nodiscard]] size_t size() const { return sourceUnitPaths.size(); } /// Prints test state to @param _os. void print(std::ostream& _os) const; - /// Returns a randomly chosen path from @param _sourceUnitPaths. + /// @returns a randomly chosen path from @param _sourceUnitPaths. [[nodiscard]] std::string randomPath(std::set const& _sourceUnitPaths) const; - /// Returns a randomly chosen path from @name sourceUnitPaths. + /// @returns a randomly chosen path from @name sourceUnitPaths. [[nodiscard]] std::string randomPath() const; - /// Returns a randomly chosen non current source unit path. + /// @returns a randomly chosen non current source unit path. [[nodiscard]] std::string randomNonCurrentPath() const; /// List of source paths in test input. std::set sourceUnitPaths; /// Source path being currently visited. std::string currentSourceUnitPath; - /// Random number generator. - std::shared_ptr rand; + /// Uniform random distribution. + std::shared_ptr uRandDist; }; struct GeneratorBase @@ -127,15 +132,15 @@ struct GeneratorBase return std::get>(g); solAssert(false, ""); } - /// Returns test fragment created by this generator. + /// @returns test fragment created by this generator. std::string generate() { std::string generatedCode = visit(); endVisit(); return generatedCode; } - /// Virtual visitor that returns a string representing - /// the generation of the Solidity grammar element. + /// @returns a string representing the generation of + /// the Solidity grammar element. virtual std::string visit() = 0; /// Method called after visiting this generator. Used /// for clearing state if necessary. @@ -162,12 +167,12 @@ struct GeneratorBase } /// Shared pointer to the mutator instance std::shared_ptr mutator; - /// Random engine shared by Solidity mutators - std::shared_ptr rand; /// Set of generators used by this generator. std::set generators; /// Shared ptr to global test state. std::shared_ptr state; + /// Uniform random distribution + std::shared_ptr uRandDist; }; class TestCaseGenerator: public GeneratorBase @@ -184,7 +189,7 @@ public: return "Test case generator"; } private: - /// Returns a new source path name that is formed by concatenating + /// @returns a new source path name that is formed by concatenating /// a static prefix @name m_sourceUnitNamePrefix, a monotonically /// increasing counter starting from 0 and the postfix (extension) /// ".sol". @@ -252,18 +257,18 @@ class SolidityGenerator: public std::enable_shared_from_this public: explicit SolidityGenerator(unsigned _seed); - /// Returns the generator of type @param T. + /// @returns the generator of type @param T. template std::shared_ptr generator(); - /// Returns a shared ptr to underlying random - /// number generator. - std::shared_ptr randomEngine() + /// @returns a shared ptr to underlying random + /// number distribution. + std::shared_ptr uniformRandomDist() { - return m_rand; + return m_urd; } - /// Returns a pseudo randomly generated test case. + /// @returns a pseudo randomly generated test case. std::string generateTestProgram(); - /// Returns shared ptr to global test state. + /// @returns shared ptr to global test state. std::shared_ptr testState() { return m_state; @@ -282,11 +287,11 @@ private: { m_generators.clear(); } - /// Random number generator - std::shared_ptr m_rand; /// Sub generators std::set m_generators; /// Shared global test state std::shared_ptr m_state; + /// Uniform random distribution + std::shared_ptr m_urd; }; }