From eab92f93a35b672e242e29ae85bc36d8c660359e Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Thu, 12 Oct 2023 13:43:22 +0200 Subject: [PATCH] Make Yul proto mutator mutations deterministic. --- .../ossfuzz/protomutators/YulProtoMutator.cpp | 28 +++++++++---------- .../ossfuzz/protomutators/YulProtoMutator.h | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp index 09001217d7a1..9b0c97a22df0 100644 --- a/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.cpp @@ -26,20 +26,18 @@ void MutationInfo::exitInfo() writeLine(SaveMessageAsText(*m_protobufMsg)); } -/// Initialize deterministic PRNG. -static YulRandomNumGenerator s_rand(1337); - /// Add m/sstore(0, variable) static LPMPostProcessor addStoreToZero( [](Block* _message, unsigned _seed) { if (_seed % YPM::s_highIP == 0) { + YulRandomNumGenerator yrand(_seed); MutationInfo m{_message, "Added store to zero"}; auto storeStmt = new StoreFunc(); - storeStmt->set_st(YPM::EnumTypeConverter{}.enumFromSeed(s_rand())); + storeStmt->set_st(YPM::EnumTypeConverter{}.enumFromSeed(yrand())); storeStmt->set_allocated_loc(YPM::litExpression(0)); - storeStmt->set_allocated_val(YPM::refExpression(s_rand)); + storeStmt->set_allocated_val(YPM::refExpression(yrand)); auto stmt = _message->add_statements(); stmt->set_allocated_storage_func(storeStmt); } @@ -54,10 +52,10 @@ struct addControlFlow { addControlFlow() { - function = [](T* _message, unsigned) + function = [](T* _message, unsigned _seed) { MutationInfo m{_message, "Added control flow."}; - YPM::addControlFlow(_message); + YPM::addControlFlow(_message, _seed); }; /// Unused variable registers callback. LPMPostProcessor callback(function); @@ -170,7 +168,7 @@ unsigned YPM::EnumTypeConverter::enumMin() } template -void YPM::addControlFlow(T* _msg) +void YPM::addControlFlow(T* _msg, unsigned _seed) { enum class ControlFlowStmt: unsigned { @@ -188,8 +186,9 @@ void YPM::addControlFlow(T* _msg) static_cast(ControlFlowStmt::For), static_cast(ControlFlowStmt::Termination) ); - auto random = static_cast(d(s_rand.m_random)); - Statement* s = basicBlock(_msg)->add_statements(); + YulRandomNumGenerator yrand(_seed); + auto random = static_cast(d(yrand.m_random)); + Statement* s = basicBlock(_msg, _seed)->add_statements(); switch (random) { case ControlFlowStmt::For: @@ -222,7 +221,7 @@ void YPM::addControlFlow(T* _msg) } } -Block* YPM::randomBlock(ForStmt* _stmt) +Block* YPM::randomBlock(ForStmt* _stmt, unsigned _seed) { enum class ForBlocks: unsigned { @@ -234,7 +233,8 @@ Block* YPM::randomBlock(ForStmt* _stmt) static_cast(ForBlocks::Init), static_cast(ForBlocks::Body) ); - switch (static_cast(d(s_rand.m_random))) + YulRandomNumGenerator yrand(_seed); + switch (static_cast(d(yrand.m_random))) { case ForBlocks::Init: return _stmt->mutable_for_init(); @@ -246,10 +246,10 @@ Block* YPM::randomBlock(ForStmt* _stmt) } template -Block* YPM::basicBlock(T* _msg) +Block* YPM::basicBlock(T* _msg, unsigned _seed) { if constexpr (std::is_same_v) - return randomBlock(_msg); + return randomBlock(_msg, _seed); else if constexpr (std::is_same_v) return _msg->mutable_for_body(); else if constexpr (std::is_same_v) diff --git a/test/tools/ossfuzz/protomutators/YulProtoMutator.h b/test/tools/ossfuzz/protomutators/YulProtoMutator.h index c6fd010ba84f..0d68b95c50ac 100644 --- a/test/tools/ossfuzz/protomutators/YulProtoMutator.h +++ b/test/tools/ossfuzz/protomutators/YulProtoMutator.h @@ -96,13 +96,13 @@ struct YulProtoMutator static constexpr unsigned s_highIP = 23; /// Add control-flow statement to basic block. template - static void addControlFlow(T* _msg); + static void addControlFlow(T* _msg, unsigned _seed); /// Obtain basic block for statement type. template - static Block* basicBlock(T* _msg); + static Block* basicBlock(T* _msg, unsigned _seed); /// Obtain a basic block in a for stmt uniformly /// at random - static Block* randomBlock(ForStmt* _msg); + static Block* randomBlock(ForStmt* _msg, unsigned _seed); /// Obtain a basic block in global scope. static Block* globalBlock(Program* _program); };