3#include <fuzzer/FuzzedDataProvider.h>
42struct AluFuzzerInput {
48 static const size_t size = (3 * (
sizeof(
FF) + 1)) +
sizeof(uint16_t);
52 auto write_mem_value = [](uint8_t* target,
MemoryValue mem_value) {
61 write_mem_value(
buffer, c);
68 auto read_mem_value = [](
const uint8_t* src) ->
MemoryValue {
75 input.a = read_mem_value(
buffer);
77 input.b = read_mem_value(
buffer);
79 input.c = read_mem_value(
buffer);
93 if (size < AluFuzzerInput::size) {
96 input.to_buffer(
data);
97 return AluFuzzerInput::size;
102 auto op_likes_matched_tags = [](
int op_id) ->
bool {
124 FF value =
FF(dist(rng), dist(rng), dist(rng), dist(rng));
130 auto random_mem_value = [&rng, random_mem_value_from_tag]() ->
MemoryValue {
133 return random_mem_value_from_tag(
tag);
137 AluFuzzerInput input = AluFuzzerInput::from_buffer(
data);
141 input.op_id =
static_cast<uint16_t
>(1 << dist(rng));
145 int choice = dist(rng);
151 input.a = random_mem_value();
156 if (op_likes_matched_tags(input.op_id)) {
157 input.b = random_mem_value_from_tag(input.a.get_tag());
160 input.b = random_mem_value();
166 input.b = random_mem_value();
167 if (op_likes_matched_tags(input.op_id)) {
168 while (input.b.get_tag() == input.a.get_tag()) {
169 input.b = random_mem_value();
181 std::swap(input.a, input.b);
189 input.to_buffer(
data);
191 if (max_size > AluFuzzerInput::size) {
192 return AluFuzzerInput::size;
195 return AluFuzzerInput::size;
202 if (size < AluFuzzerInput::size) {
203 info(
"Input size too small");
207 AluFuzzerInput input = AluFuzzerInput::from_buffer(
data);
225 switch (input.op_id) {
227 input.c =
alu.add(input.a, input.b);
228 assert(input.c == input.a + input.b);
232 input.c =
alu.sub(input.a, input.b);
233 assert(input.c == input.a - input.b);
237 input.c =
alu.mul(input.a, input.b);
238 assert(input.c == input.a * input.b);
242 input.c =
alu.div(input.a, input.b);
243 assert(input.c == input.a / input.b);
247 input.c =
alu.fdiv(input.a, input.b);
248 assert(input.c == input.a / input.b);
252 input.c =
alu.eq(input.a, input.b);
258 input.c =
alu.lt(input.a, input.b);
264 input.c =
alu.lte(input.a, input.b);
272 input.b =
alu.op_not(input.a);
273 assert(input.b == ~input.a);
277 input.c =
alu.shr(input.a, input.b);
278 assert(input.c == (input.a >> input.b));
282 input.c =
alu.shl(input.a, input.b);
283 assert(input.c == (input.a << input.b));
287 input.c =
alu.truncate(input.a, input.b.get_tag());
302 { Column::execution_register_0_, input.a.as_ff() },
303 { Column::execution_register_1_, input.c.as_ff() },
304 { Column::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(input.b.get_tag()) },
305 { Column::execution_rop_2_,
static_cast<uint8_t
>(input.b.get_tag()) },
306 { Column::execution_sel_exec_dispatch_cast, 1 },
307 { Column::execution_sel_opcode_error, 0 },
312 { Column::execution_mem_tag_reg_0_,
static_cast<uint8_t
>(input.a.get_tag()) },
313 { Column::execution_mem_tag_reg_1_,
static_cast<uint8_t
>(input.b.get_tag()) },
314 { Column::execution_mem_tag_reg_2_,
static_cast<uint8_t
>(input.c.get_tag()) },
315 { Column::execution_register_0_, input.a.as_ff() },
316 { Column::execution_register_1_, input.b.as_ff() },
317 { Column::execution_register_2_, input.c.as_ff() },
318 { Column::execution_sel_exec_dispatch_alu, 1 },
319 { Column::execution_sel_opcode_error, error ? 1 : 0 },
320 { Column::execution_subtrace_operation_id, input.op_id },
341 if (getenv(
"AVM_DEBUG") !=
nullptr) {
342 info(
"Debugging trace:");
347 check_relation<alu_rel>(
trace);
348 check_all_interactions<AluTraceBuilder>(
trace);
351 check_interaction<ExecutionTraceBuilder, bb::avm2::lookup_execution_dispatch_to_cast_settings>(
trace);
353 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)
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
FieldGreaterThan field_gt
EventEmitter< simulation::FieldGreaterThanEvent > field_gt_emitter
EventEmitter< simulation::RangeCheckEvent > range_check_emitter
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)
Processes FieldGreaterThanEvent events and generates trace rows for the ff_gt gadget.
void process(const simulation::EventEmitterInterface< simulation::GreaterThanEvent >::Container &events, TraceContainer &trace)
Process the greater-than events and populate the relevant columns in the trace.
void process_misc(TraceContainer &trace, const uint32_t num_rows=PRECOMPUTED_TRACE_SIZE)
Populate miscellaneous precomputed columns: first_row selector and idx (row index).
void process_power_of_2(TraceContainer &trace)
Generate a column where row i holds 2^i, for i in [0, 255], for the values of 254 and 255 the values ...
void process_tag_parameters(TraceContainer &trace)
Populate the memory tag parameters table (byte length, max bits, max value per tag).
void process_sel_range_8(TraceContainer &trace)
Generate a selector column that activates the first 2^8 (256) rows.
void process(const simulation::EventEmitterInterface< simulation::RangeCheckEvent >::Container &events, TraceContainer &trace)
Processes range check events and populates the trace with decomposed value columns.
RangeCheckTraceBuilder range_check_builder
PrecomputedTraceBuilder precomputed_builder
FieldGreaterThanTraceBuilder field_gt_builder
GreaterThanTraceBuilder gt_builder
const std::vector< MemoryValue > data
std::unique_ptr< uint8_t[]> buffer
AVM range check gadget for witness generation.
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by SERIALIZATIO...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by SERIALIZATI...
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)