3#include <fuzzer/FuzzedDataProvider.h>
43struct AluFuzzerInput {
52 auto write_mem_value = [](uint8_t* target,
MemoryValue mem_value) {
61 write_mem_value(
buffer, c);
93 if (size <
sizeof(AluFuzzerInput)) {
96 input.to_buffer(
data);
97 return sizeof(AluFuzzerInput);
102 auto op_likes_matched_tags = [](
int op_id) ->
bool {
125 FF value =
FF(dist(rng), dist(rng), dist(rng), dist(rng));
131 auto random_mem_value = [&rng, random_mem_value_from_tag]() ->
MemoryValue {
134 return random_mem_value_from_tag(
tag);
138 AluFuzzerInput input = AluFuzzerInput::from_buffer(
data);
142 input.op_id = 1 << dist(rng);
146 int choice = dist(rng);
152 input.a = random_mem_value();
157 if (op_likes_matched_tags(input.op_id)) {
158 input.b = random_mem_value_from_tag(input.a.get_tag());
161 input.b = random_mem_value();
167 input.b = random_mem_value();
168 if (op_likes_matched_tags(input.op_id)) {
169 while (input.b.get_tag() == input.a.get_tag()) {
170 input.b = random_mem_value();
182 std::swap(input.a, input.b);
190 input.to_buffer(
data);
192 if (max_size >
sizeof(AluFuzzerInput)) {
193 return sizeof(AluFuzzerInput);
196 return sizeof(AluFuzzerInput);
203 if (size <
sizeof(AluFuzzerInput)) {
204 info(
"Input size too small");
208 AluFuzzerInput input = AluFuzzerInput::from_buffer(
data);
226 switch (input.op_id) {
228 input.c =
alu.add(input.a, input.b);
229 assert(input.c == input.a + input.b);
233 input.c =
alu.sub(input.a, input.b);
234 assert(input.c == input.a - input.b);
238 input.c =
alu.mul(input.a, input.b);
239 assert(input.c == input.a * input.b);
243 input.c =
alu.div(input.a, input.b);
244 assert(input.c == input.a / input.b);
248 input.c =
alu.fdiv(input.a, input.b);
249 assert(input.c == input.a / input.b);
253 input.c =
alu.eq(input.a, input.b);
259 input.c =
alu.lt(input.a, input.b);
265 input.c =
alu.lte(input.a, input.b);
273 input.b =
alu.op_not(input.a);
274 assert(input.b == ~input.a);
278 input.c =
alu.shr(input.a, input.b);
279 assert(input.c == (input.a >> input.b));
283 input.c =
alu.shl(input.a, input.b);
284 assert(input.c == (input.a << input.b));
288 input.c =
alu.truncate(input.a, input.b.get_tag());
303 { avm2::Column::execution_register_0_, input.a.as_ff() },
304 { avm2::Column::execution_register_1_, input.c.as_ff() },
305 { avm2::Column::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(input.b.get_tag()) },
306 { avm2::Column::execution_rop_2_,
static_cast<uint8_t
>(input.b.get_tag()) },
307 { avm2::Column::execution_sel_exec_dispatch_cast, 1 },
308 { avm2::Column::execution_sel_opcode_error, 0 },
313 { avm2::Column::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(input.a.get_tag()) },
314 { avm2::Column::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(input.b.get_tag()) },
315 { avm2::Column::execution_mem_tag_reg_2_,
static_cast<uint8_t
>(input.c.get_tag()) },
316 { avm2::Column::execution_register_0_, input.a.as_ff() },
317 { avm2::Column::execution_register_1_, input.b.as_ff() },
318 { avm2::Column::execution_register_2_, input.c.as_ff() },
319 { avm2::Column::execution_sel_exec_dispatch_alu, 1 },
320 { avm2::Column::execution_sel_opcode_error, error ? 1 : 0 },
321 { avm2::Column::execution_subtrace_operation_id, input.op_id },
342 if (getenv(
"AVM_DEBUG") !=
nullptr) {
343 info(
"Debugging trace:");
348 check_relation<alu_rel>(
trace);
349 check_all_interactions<AluTraceBuilder>(
trace);
352 check_interaction<ExecutionTraceBuilder, bb::avm2::lookup_execution_dispatch_to_cast_settings>(
trace);
354 check_interaction<ExecutionTraceBuilder, bb::avm2::lookup_execution_dispatch_to_alu_settings>(
trace);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
size_t LLVMFuzzerCustomMutator(uint8_t *data, size_t size, size_t max_size, unsigned int seed)
DeduplicatingEventEmitter< FieldGreaterThanEvent > field_gt_emitter
FieldGreaterThan field_gt
DeduplicatingEventEmitter< RangeCheckEvent > range_check_emitter
EventEmitter< AluEvent > alu_emitter
#define AVM_EXEC_OP_ID_ALU_TRUNCATE
#define AVM_EXEC_OP_ID_ALU_LTE
#define AVM_EXEC_OP_ID_ALU_DIV
#define AVM_EXEC_OP_ID_ALU_ADD
#define AVM_EXEC_OP_ID_ALU_SHL
#define AVM_EXEC_OP_ID_ALU_EQ
#define AVM_EXEC_OP_ID_ALU_SUB
#define AVM_EXEC_OP_ID_ALU_NOT
#define AVM_EXEC_OP_ID_ALU_MUL
#define AVM_EXEC_OP_ID_ALU_FDIV
#define AVM_EXEC_OP_ID_ALU_SHR
#define AVM_EXEC_OP_ID_ALU_LT
void run(uint32_t starting_row=0)
static TaggedValue from_tag_truncating(ValueTag tag, FF value)
static TaggedValue from_tag(ValueTag tag, FF value)
EventEmitter< Event >::Container dump_events()
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
Process the ALU events and populate the ALU relevant columns in the trace.
void process(const simulation::EventEmitterInterface< simulation::FieldGreaterThanEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::GreaterThanEvent >::Container &events, TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_power_of_2(TraceContainer &trace)
void process_tag_parameters(TraceContainer &trace)
void process_sel_range_8(TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::RangeCheckEvent >::Container &events, TraceContainer &trace)
RangeCheckTraceBuilder range_check_builder
PrecomputedTraceBuilder precomputed_builder
FieldGreaterThanTraceBuilder field_gt_builder
GreaterThanTraceBuilder gt_builder
const std::vector< MemoryValue > data
uint8_t buffer[RANDOM_BUFFER_SIZE]
MemoryValue read_mem_value(FuzzedDataProvider &fdp)
Read a MemoryValue from the fuzzed data provider.
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by MSGPACK_FIEL...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by MSGPACK_FIE...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
T from_buffer(B const &buffer, size_t offset=0)
std::vector< uint8_t > to_buffer(T const &value)
static field serialize_from_buffer(const uint8_t *buffer)
static void serialize_to_buffer(const field &value, uint8_t *buffer)