mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
110 lines
2.9 KiB
C++
110 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include <test/tools/ossfuzz/yulProto.pb.h>
|
|
|
|
#include <libsolutil/Common.h>
|
|
|
|
#include <src/libfuzzer/libfuzzer_macro.h>
|
|
|
|
#include <random>
|
|
|
|
namespace solidity::yul::test::yul_fuzzer
|
|
{
|
|
|
|
using ProtobufMessage = google::protobuf::Message;
|
|
|
|
template <typename Proto>
|
|
using LPMPostProcessor = protobuf_mutator::libfuzzer::PostProcessorRegistration<Proto>;
|
|
|
|
class MutationInfo: public ScopeGuard
|
|
{
|
|
public:
|
|
MutationInfo(ProtobufMessage const* _message, std::string const& _info);
|
|
|
|
static void writeLine(std::string const& _str)
|
|
{
|
|
std::cout << _str << std::endl;
|
|
}
|
|
void exitInfo();
|
|
|
|
ProtobufMessage const* m_protobufMsg;
|
|
};
|
|
|
|
struct YulRandomNumGenerator
|
|
{
|
|
using RandomEngine = std::minstd_rand;
|
|
|
|
explicit YulRandomNumGenerator(unsigned _seed): m_random(RandomEngine(_seed)) {}
|
|
|
|
unsigned operator()()
|
|
{
|
|
return static_cast<unsigned>(m_random());
|
|
}
|
|
|
|
RandomEngine m_random;
|
|
};
|
|
|
|
struct YulProtoMutator
|
|
{
|
|
/// @param _value: Value of the integer literal
|
|
/// @returns an integer literal protobuf message initialized with
|
|
/// the given value.
|
|
static Literal* intLiteral(unsigned _value);
|
|
|
|
/// @param _seed: Pseudo-random unsigned integer used as index
|
|
/// of variable to be referenced
|
|
/// @returns a variable reference protobuf message.
|
|
static VarRef* varRef(unsigned _seed);
|
|
|
|
/// @param _value: value of literal expression
|
|
/// @returns an expression protobuf message
|
|
static Expression* litExpression(unsigned _value);
|
|
|
|
/// @param _rand: Pseudo-random number generator
|
|
/// of variable to be referenced
|
|
/// @returns a variable reference protobuf message
|
|
static Expression* refExpression(YulRandomNumGenerator& _rand);
|
|
|
|
/// Helper type for type matching visitor.
|
|
template<class T> struct AlwaysFalse: std::false_type {};
|
|
|
|
/// Template struct for obtaining a valid enum value of
|
|
/// template type from a pseudo-random unsigned integer.
|
|
/// @param _seed: Pseudo-random integer
|
|
/// @returns Valid enum of enum type T
|
|
template <typename T>
|
|
struct EnumTypeConverter
|
|
{
|
|
T enumFromSeed(unsigned _seed)
|
|
{
|
|
return validEnum(_seed);
|
|
}
|
|
|
|
/// @returns a valid enum of type T from _seed
|
|
T validEnum(unsigned _seed);
|
|
/// @returns maximum enum value for enum of type T
|
|
static unsigned enumMax();
|
|
/// @returns minimum enum value for enum of type T
|
|
static unsigned enumMin();
|
|
};
|
|
|
|
/// Modulo for mutations that should occur rarely
|
|
static constexpr unsigned s_lowIP = 31;
|
|
/// Modulo for mutations that should occur not too often
|
|
static constexpr unsigned s_mediumIP = 29;
|
|
/// Modulo for mutations that should occur often
|
|
static constexpr unsigned s_highIP = 23;
|
|
/// Add control-flow statement to basic block.
|
|
template <typename T>
|
|
static void addControlFlow(T* _msg);
|
|
/// Obtain basic block for statement type.
|
|
template <typename T>
|
|
static Block* basicBlock(T* _msg);
|
|
/// Obtain a basic block in a for stmt uniformly
|
|
/// at random
|
|
static Block* randomBlock(ForStmt* _msg);
|
|
/// Obtain a basic block in global scope.
|
|
static Block* globalBlock(Program* _program);
|
|
};
|
|
}
|