Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bitwise.fuzzer.cpp
Go to the documentation of this file.
1#include <cstdint>
2#include <fuzzer/FuzzedDataProvider.h>
3
20
21using namespace bb::avm2::simulation;
22using namespace bb::avm2::tracegen;
23using namespace bb::avm2::constraining;
24using namespace bb::avm2::fuzzing;
25
26using bb::avm2::FF;
29
31
32// We initialize it here once so it can be shared to other threads.
33// We don't use LLVMFuzzerInitialize since (IIUC) it is not thread safe and we want to run this
34// with multiple worker threads.
35static const TestTraceContainer precomputed_trace = []() {
40 precomputed_builder.process_misc(t, 1 << 18); // Need enough for bitwise trace
41 return t;
42}();
43
44// Each worker thread gets its own trace, initialized from precomputed_trace
45thread_local static TestTraceContainer trace = precomputed_trace;
46
47extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
48{
50
51 // two uint256 + <int>op_type + <int>tag_choice
52 size_t minimum_size = 64 + (sizeof(int) * 2);
53
54 if (size < minimum_size) {
55 return 0;
56 }
57
58 // Fuzzed Data Provider helps with extracting typed data from the raw byte stream.
59 FuzzedDataProvider fuzzed_data(data, size);
60
61 MemoryValue a = read_mem_value(fuzzed_data);
62 MemoryValue b = read_mem_value(fuzzed_data);
63
64 MemoryValue c = MemoryValue::from_tag(MemoryTag::FF, 0); // Placeholder for result
65 int op_id = 0; // For execution trace bitwise_op_id
66
67 int op_type = fuzzed_data.ConsumeIntegralInRange<int>(0, 2);
68
69 // Set up gadgets and event emitters
71
72 bool bitwise_error = false;
73
74 Bitwise bitwise(bitwise_emitter);
75 // Pick and execute operation
76 try {
77 switch (op_type) {
78 case 0: {
80 c = bitwise.and_op(a, b);
81 break;
82 }
83 case 1: {
85 c = bitwise.or_op(a, b);
86 break;
87 }
88 case 2: {
90 c = bitwise.xor_op(a, b);
91 break;
92 }
93 default:
94 return 0;
95 }
96 } catch (const BitwiseException& e) {
97 // Bitwise Errors are recoverable
98 bitwise_error = true;
99 }
100
101 // info("Fuzz Input: a: ", a.to_string(), ", b: ", b.to_string(), ", op_type: ", op_type);
102 // Set execution trace columns
103 trace.set(0,
104 { {
105 { avm2::Column::execution_mem_tag_reg_0_, static_cast<uint8_t>(a.get_tag()) }, // = ia_tag
106 { avm2::Column::execution_mem_tag_reg_1_, static_cast<uint8_t>(b.get_tag()) }, // = ib_tag
107 { avm2::Column::execution_mem_tag_reg_2_, static_cast<uint8_t>(c.get_tag()) }, // = ic_tag
108 { avm2::Column::execution_register_0_, a.as_ff() }, // = ia
109 { avm2::Column::execution_register_1_, b.as_ff() }, // = ib
110 { avm2::Column::execution_register_2_, c.as_ff() }, // = ic
111 { avm2::Column::execution_sel_exec_dispatch_bitwise, 1 }, // = sel
112 { avm2::Column::execution_sel_opcode_error, bitwise_error ? 1 : 0 }, // = sel_err
113 { avm2::Column::execution_subtrace_operation_id, op_id }, // = bitwise_op_id
114
115 } });
116
118 builder.process(bitwise_emitter.dump_events(), trace);
119
120 if (getenv("AVM_DEBUG") != nullptr) {
121 info("Debugging trace:");
122 bb::avm2::InteractiveDebugger debugger(trace);
123 debugger.run();
124 }
125
126 check_relation<bitwise_rel>(trace);
127 check_all_interactions<BitwiseTraceBuilder>(trace);
128 check_interaction<ExecutionTraceBuilder, bb::avm2::lookup_execution_dispatch_to_bitwise_settings>(trace);
129
130 // Reset the bitwise portion of the trace for the next iteration, bitwise portion begins at row 1 and can maximally
131 // create 16 additional rows(for U128). Therefore we reset rows [1, 17] This could be done more optimally by only
132 // resetting get_tag_bytes(a.get_tag()) rows.
133 for (uint8_t i = 1; i < 17; i++) {
134 trace.set(i,
135 { {
136 { avm2::Column::bitwise_op_id, 0 },
137 { avm2::Column::bitwise_start, 0 },
138 { avm2::Column::bitwise_sel_get_ctr, 0 },
139 { avm2::Column::bitwise_last, 0 },
140 { avm2::Column::bitwise_acc_ia, 0 },
141 { avm2::Column::bitwise_acc_ib, 0 },
142 { avm2::Column::bitwise_acc_ic, 0 },
143 { avm2::Column::bitwise_ia_byte, 0 },
144 { avm2::Column::bitwise_ib_byte, 0 },
145 { avm2::Column::bitwise_ic_byte, 0 },
146 { avm2::Column::bitwise_tag_a, 0 },
147 { avm2::Column::bitwise_tag_b, 0 },
148 { avm2::Column::bitwise_tag_c, 0 },
149 { avm2::Column::bitwise_sel_tag_ff_err, 0 },
150 { avm2::Column::bitwise_sel_tag_mismatch_err, 0 },
151 { avm2::Column::bitwise_err, 0 },
152 { avm2::Column::bitwise_tag_a_inv, 0 },
153 { avm2::Column::bitwise_tag_ab_diff_inv, 0 },
154 { avm2::Column::bitwise_ctr, 0 },
155 { avm2::Column::bitwise_ctr_inv, 0 },
156 { avm2::Column::bitwise_ctr_min_one_inv, 0 },
157 { avm2::Column::bitwise_sel, 0 },
158 { avm2::Column::bitwise_tag_a_inv, 0 },
159 { avm2::Column::bitwise_tag_ab_diff_inv, 0 },
160 } });
161 }
162
163 return 0;
164}
#define AVM_BITWISE_AND_OP_ID
#define AVM_BITWISE_OR_OP_ID
#define AVM_BITWISE_XOR_OP_ID
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
void run(uint32_t starting_row=0)
Definition debugger.cpp:76
static TaggedValue from_tag(ValueTag tag, FF value)
ValueTag get_tag() const
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_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void set(Column col, uint32_t row, const FF &value)
void info(Args... args)
Definition log.hpp:75
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:120
AluTraceBuilder builder
Definition alu.test.cpp:124
const std::vector< MemoryValue > data
FF a
FF b
MemoryValue read_mem_value(FuzzedDataProvider &fdp)
Read a MemoryValue from the fuzzed data provider.
AvmFlavorSettings::FF FF
Definition field.hpp:10