8#pragma clang diagnostic push
9#pragma clang diagnostic ignored "-Wc99-designator"
22#define OPERATION_TYPE_SIZE 1
24#define ELEMENT_SIZE (sizeof(fr) + 1)
25#define TWO_IN_ONE_OUT 3
26#define THREE_IN_ONE_OUT 4
27#define SLICE_ARGS_SIZE 6
45 enum OPCODE {
CONSTANT,
WITNESS,
AND,
OR,
XOR,
NOT,
ASSERT_EQUAL,
SELECT_IF_EQ,
SET,
RANDOMSEED,
_LAST };
86 uint8_t in1, in2, in3, out;
88 switch (instruction_opcode) {
92 return { .id = instruction_opcode, .arguments.element =
static_cast<bool>(rng.next() % 2) };
99 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
100 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
101 out =
static_cast<uint8_t
>(rng.next() & 0xff);
102 return { .id = instruction_opcode, .arguments.threeArgs = { .in1 = in1, .in2 = in2, .out = out } };
107 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
108 in2 =
static_cast<uint8_t
>(rng.next() & 0xff);
109 in3 =
static_cast<uint8_t
>(rng.next() & 0xff);
110 out =
static_cast<uint8_t
>(rng.next() & 0xff);
111 return { .id = instruction_opcode,
112 .arguments.fourArgs{ .in1 = in1, .in2 = in2, .in3 = in3, .out = out } };
117 in1 =
static_cast<uint8_t
>(rng.next() & 0xff);
118 out =
static_cast<uint8_t
>(rng.next() & 0xff);
119 return { .id = instruction_opcode, .arguments.twoArgs = { .in = in1, .out = out } };
121 return { .id = instruction_opcode, .arguments.randomseed = rng.next() };
138 template <
typename T>
144#define PUT_RANDOM_BYTE_IF_LUCKY(variable) \
145 if (rng.next() & 1) { \
146 variable = rng.next() & 0xff; \
148#define PUT_RANDOM_TWO_BYTES_IF_LUCKY(variable) \
149 if (rng.next() & 1) { \
150 variable = rng.next() & 0xffff; \
152#define PUT_RANDOM_FOUR_BYTES_IF_LUCKY(variable) \
153 if (rng.next() & 1) { \
154 variable = rng.next() & 0xffffffff; \
199 static constexpr size_t AND = 3;
200 static constexpr size_t OR = 3;
201 static constexpr size_t XOR = 3;
203 static constexpr size_t NOT = 2;
205 static constexpr size_t SET = 2;
225 .arguments.element =
static_cast<bool>(*Data) };
230 .arguments.threeArgs = { .in1 = *Data, .in2 = *(Data + 1), .out = *(Data + 2) } };
235 .arguments.twoArgs = { .in = *Data, .out = *(Data + 1) } };
240 .arguments.fourArgs = {
241 .in1 = *Data, .in2 = *(Data + 1), .in3 = *(Data + 2), .out = *(Data + 3) } };
243 if constexpr (opcode == Instruction::OPCODE::RANDOMSEED) {
245 memcpy(&randomseed, Data,
sizeof(uint32_t));
246 return Instruction{ .id =
static_cast<typename Instruction::OPCODE
>(opcode),
247 .arguments.randomseed = randomseed };
257 template <
typename Instruction::OPCODE instruction_opcode>
260 if constexpr (instruction_opcode == Instruction::OPCODE::CONSTANT ||
261 instruction_opcode == Instruction::OPCODE::WITNESS) {
263 *(Data + 1) =
instruction.arguments.element ? 1 : 0;
265 if constexpr (instruction_opcode == Instruction::OPCODE::AND ||
266 instruction_opcode == Instruction::OPCODE::OR ||
267 instruction_opcode == Instruction::OPCODE::XOR) {
273 if constexpr (instruction_opcode == Instruction::OPCODE::NOT ||
274 instruction_opcode == Instruction::OPCODE::ASSERT_EQUAL ||
275 instruction_opcode == Instruction::OPCODE::SET) {
280 if constexpr (instruction_opcode == Instruction::OPCODE::SELECT_IF_EQ) {
287 if constexpr (instruction_opcode == Instruction::OPCODE::RANDOMSEED) {
290 memcpy(Data + 1, &
instruction.arguments.randomseed,
sizeof(uint32_t));
309 : reference_value(
b.get_value())
391 : this->reference_value,
392 (other1.
b == other2.
b).get_value() ? other1.
b : this->
b);
454 if (stack.size() == 0) {
457 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
458 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
459 size_t output_index =
instruction.arguments.threeArgs.out;
462 result = stack[first_index] & stack[second_index];
464 if (output_index >= stack.size()) {
465 stack.push_back(result);
467 stack[output_index] = result;
484 if (stack.size() == 0) {
487 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
488 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
489 size_t output_index =
instruction.arguments.threeArgs.out;
492 result = stack[first_index] | stack[second_index];
494 if (output_index >= stack.size()) {
495 stack.push_back(result);
497 stack[output_index] = result;
514 if (stack.size() == 0) {
517 size_t first_index =
instruction.arguments.threeArgs.in1 % stack.size();
518 size_t second_index =
instruction.arguments.threeArgs.in2 % stack.size();
519 size_t output_index =
instruction.arguments.threeArgs.out;
522 result = stack[first_index] ^ stack[second_index];
524 if (output_index >= stack.size()) {
525 stack.push_back(result);
527 stack[output_index] = result;
544 if (stack.size() == 0) {
547 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
548 size_t output_index =
instruction.arguments.twoArgs.out;
551 result = stack[first_index].
not_();
553 if (output_index >= stack.size()) {
554 stack.push_back(result);
556 stack[output_index] = result;
573 if (stack.size() == 0) {
576 size_t first_index =
instruction.arguments.fourArgs.in1 % stack.size();
577 size_t second_index =
instruction.arguments.fourArgs.in2 % stack.size();
578 size_t third_index =
instruction.arguments.fourArgs.in3 % stack.size();
579 size_t output_index =
instruction.arguments.fourArgs.out % stack.size();
582 result = stack[first_index].
select_if_eq(stack[second_index], stack[third_index]);
584 if (output_index >= stack.size()) {
585 stack.push_back(result);
587 stack[output_index] = result;
604 if (stack.size() == 0) {
607 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
608 size_t second_index =
instruction.arguments.twoArgs.out % stack.size();
610 stack[first_index].assert_equal(stack[second_index]);
626 if (stack.size() == 0) {
629 size_t first_index =
instruction.arguments.twoArgs.in % stack.size();
630 size_t output_index =
instruction.arguments.twoArgs.out;
634 if (output_index >= stack.size()) {
635 stack.push_back(result);
637 stack[output_index] = result;
674 for (
size_t i = 0; i < stack.size(); i++) {
675 auto element = stack[i];
676 if (element.b.get_value() != element.reference_value) {
677 printf(
"Other: %d", element.b.get_value());
678 printf(
"Reference value: %d\n", element.reference_value);
696 .GEN_MUTATION_COUNT_LOG = 5,
697 .GEN_STRUCTURAL_MUTATION_PROBABILITY = 300,
698 .GEN_VALUE_MUTATION_PROBABILITY = 700,
699 .ST_MUT_DELETION_PROBABILITY = 100,
700 .ST_MUT_DUPLICATION_PROBABILITY = 80,
701 .ST_MUT_INSERTION_PROBABILITY = 120,
702 .ST_MUT_MAXIMUM_DELETION_LOG = 6,
703 .ST_MUT_MAXIMUM_DUPLICATION_LOG = 2,
704 .ST_MUT_SWAP_PROBABILITY = 50,
705 .VAL_MUT_LLVM_MUTATE_PROBABILITY = 250,
706 .VAL_MUT_MONTGOMERY_PROBABILITY = 130,
707 .VAL_MUT_NON_MONTGOMERY_PROBABILITY = 50,
708 .VAL_MUT_SMALL_ADDITION_PROBABILITY = 110,
709 .VAL_MUT_SPECIAL_VALUE_PROBABILITY = 130
776 std::vector<size_t> structural_mutation_distribution;
777 std::vector<size_t> value_mutation_distribution;
779 temp += fuzzer_havoc_settings.ST_MUT_DELETION_PROBABILITY;
780 structural_mutation_distribution.push_back(temp);
781 temp += fuzzer_havoc_settings.ST_MUT_DUPLICATION_PROBABILITY;
782 structural_mutation_distribution.push_back(temp);
783 temp += fuzzer_havoc_settings.ST_MUT_INSERTION_PROBABILITY;
784 structural_mutation_distribution.push_back(temp);
785 temp += fuzzer_havoc_settings.ST_MUT_SWAP_PROBABILITY;
786 structural_mutation_distribution.push_back(temp);
787 fuzzer_havoc_settings.structural_mutation_distribution = structural_mutation_distribution;
790 temp += fuzzer_havoc_settings.VAL_MUT_LLVM_MUTATE_PROBABILITY;
791 value_mutation_distribution.push_back(temp);
792 temp += fuzzer_havoc_settings.VAL_MUT_SMALL_ADDITION_PROBABILITY;
793 value_mutation_distribution.push_back(temp);
795 temp += fuzzer_havoc_settings.VAL_MUT_SPECIAL_VALUE_PROBABILITY;
796 value_mutation_distribution.push_back(temp);
797 fuzzer_havoc_settings.value_mutation_distribution = value_mutation_distribution;
808 RunWithBuilders<BoolFuzzBase, FuzzerCircuitTypes>(Data, Size,
VarianceRNG);
812#pragma clang diagnostic pop
FastRandom VarianceRNG(0)
FastRandom VarianceRNG(0)
int LLVMFuzzerInitialize(int *argc, char ***argv)
size_t LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Fuzzer entry function.
#define PUT_RANDOM_BYTE_IF_LUCKY(variable)
static constexpr size_t XOR
static constexpr size_t WITNESS
static constexpr size_t OR
static constexpr size_t ASSERT_EQUAL
static constexpr size_t CONSTANT
static constexpr size_t SET
static constexpr size_t NOT
static constexpr size_t AND
static constexpr size_t SELECT_IF_EQ
static constexpr size_t RANDOMSEED
This class implements the execution of safeuint with an oracle to detect discrepancies.
static size_t execute_SET(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SET instruction.
ExecutionHandler(bool_t b)
static size_t execute_CONSTANT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the constant instruction (push constant bool_t to the stack)
ExecutionHandler(bool r, bool_t b)
static size_t execute_XOR(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the xor operator instruction.
static size_t execute_SELECT_IF_EQ(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the SELECT_IF_EQ instruction.
static size_t execute_OR(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the or operator instruction.
static size_t execute_RANDOMSEED(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the RANDOMSEED instruction.
static size_t execute_AND(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the and operator instruction.
ExecutionHandler operator|(const ExecutionHandler &other) const
static size_t execute_NOT(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the NOT instruction.
void assert_equal(ExecutionHandler &other) const
static size_t execute_WITNESS(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the witness instruction (push witness bool_t to the stack)
ExecutionHandler not_() const
ExecutionHandler operator&(const ExecutionHandler &other) const
ExecutionHandler operator^(const ExecutionHandler &other) const
ExecutionHandler select_if_eq(ExecutionHandler &other1, ExecutionHandler &other2)
static size_t execute_ASSERT_EQUAL(Builder *builder, std::vector< ExecutionHandler > &stack, Instruction &instruction)
Execute the ASSERT_EQUAL instruction.
ExecutionHandler set(Builder *builder)
ExecutionHandler()=default
A class representing a single fuzzing instruction.
static Instruction generateRandom(T &rng)
Generate a random instruction.
static Instruction mutateInstruction(Instruction instruction, T &rng, HavocSettings &havoc_config)
Mutate a single instruction.
ArgumentContents arguments
Parser class handles the parsing and writing the instructions back to data buffer.
static void writeInstruction(Instruction &instruction, uint8_t *Data)
Write a single instruction to buffer.
static Instruction parseInstructionArgs(uint8_t *Data)
Parse a single instruction from data.
The class parametrizing ByteArray fuzzing instructions, execution, etc.
bb::stdlib::witness_t< Builder > witness_t
static bool postProcess(Builder *builder, std::vector< BoolFuzzBase::ExecutionHandler > &stack)
Check that the resulting values are equal to expected.
bb::stdlib::bool_t< Builder > bool_t
std::vector< ExecutionHandler > ExecutionState
Class for quickly deterministically creating new random values. We don't care about distribution much...
void reseed(uint32_t seed)
Implements boolean logic in-circuit.
void assert_equal(const bool_t &rhs, std::string const &msg="bool_t::assert_equal") const
Implements copy constraint for bool_t elements.
Concept for a simple PRNG which returns a uint32_t when next is called.
Instruction
Enumeration of VM instructions that can be executed.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
size_t GEN_LLVM_POST_MUTATION_PROB