Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,13 @@ libfuzzer_sys::fuzz_target!(|data: &[u8]| -> Corpus {

// Disable some instructions with bugs that are not fixed yet
let instruction_options = InstructionOptions {
// https://github.com/noir-lang/noir/issues/9707
shr_enabled: false,
shl_enabled: false,
// https://github.com/noir-lang/noir/issues/9437
array_get_enabled: false,
array_set_enabled: false,
// https://github.com/noir-lang/noir/issues/9559
point_add_enabled: false,
multi_scalar_mul_enabled: false,
// https://github.com/noir-lang/noir/issues/9619
// https://github.com/noir-lang/noir/issues/10037
ecdsa_secp256k1_enabled: false,
ecdsa_secp256r1_enabled: false,
..InstructionOptions::default()
Expand Down
38 changes: 30 additions & 8 deletions tooling/ssa_fuzzer/fuzzer/src/brillig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use noirc_evaluator::ssa::ir::function::RuntimeType;
use noirc_frontend::monomorphization::ast::InlineType as FrontendInlineType;
use rand::{SeedableRng, rngs::StdRng};
use sancov::Counters;

Check warning on line 25 in tooling/ssa_fuzzer/fuzzer/src/brillig.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (sancov)
use serde::Deserialize;
use serde_json::{Value, json};
use std::fs;
Expand Down Expand Up @@ -238,18 +238,35 @@
.map_err(|e| format!("Failed to decode simulator response from base64: {e}"))
{
Ok(response_line) => response_line,
Err(e) => panic!("Failed to decode simulator response: {e}"),
Err(e) => {
if e.to_string().contains("unexpected end of file") {
log::warn!("Unexpected end of file, recreating simulator");
recreate_simulator().expect("Failed to recreate simulator");
return self.execute(bytecode, inputs);
} else {
panic!("Failed to decode simulator response: {e}");
}
}
};

let gz_decode_step = Instant::now();
let mut gz_decoder = GzDecoder::new(response_line_gzip.as_slice());
let mut response_line = Vec::new();
let result = gz_decoder
match gz_decoder
.read_to_end(&mut response_line)
.map_err(|e| format!("Failed to read simulator response: {e}"));
if result.is_err() {
panic!("Failed to read simulator response, gzip decoder: {}", result.err().unwrap());
}
.map_err(|e| format!("Failed to read simulator response: {e}"))
{
Ok(_) => (),
Err(e) => {
if e.to_string().contains("unexpected end of file") {
log::warn!("Unexpected end of file, recreating simulator");
recreate_simulator().expect("Failed to recreate simulator");
return self.execute(bytecode, inputs);
} else {
panic!("Failed to decode simulator response: {e}");
}
}
};
let response_line = String::from_utf8(response_line).unwrap();
log::debug!("Gz decoding response time {:?}", gz_decode_step.elapsed());
log::debug!("Decoding response time {:?}", decode_step.elapsed());
Expand Down Expand Up @@ -355,18 +372,23 @@
// You can disable some instructions with bugs that are not fixed yet
let modes = vec![FuzzerMode::NonConstant];
let instruction_options = InstructionOptions {
array_get_enabled: false,
array_set_enabled: false,
// https://github.com/AztecProtocol/aztec-packages/issues/17182
// all of them use to_le_radix
ecdsa_secp256k1_enabled: false,
ecdsa_secp256r1_enabled: false,
blake2s_hash_enabled: false,
blake3_hash_enabled: false,
aes128_encrypt_enabled: false,
field_to_bytes_to_field_enabled: false,
// https://github.com/AztecProtocol/aztec-packages/issues/16948
point_add_enabled: false,
multi_scalar_mul_enabled: false,
// https://github.com/AztecProtocol/aztec-packages/issues/16944
shl_enabled: false,
shr_enabled: false,

//https://github.com/noir-lang/noir/issues/10035
unsafe_get_set_enabled: false,
..InstructionOptions::default()
};
let fuzzer_command_options =
Expand Down
79 changes: 23 additions & 56 deletions tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,8 @@ impl BlockContext {
/*is constant =*/ false,
safe_index,
);
if let Some((value, is_references)) = value {
if !is_references {
self.store_variable(&value);
} else {
panic!("References are not supported for array get with dynamic index");
}
if let Some(value) = value {
self.store_variable(&value);
}
}
Instruction::ArraySet { array_index, index, value_index, safe_index } => {
Expand All @@ -384,30 +380,24 @@ impl BlockContext {
value_index,
safe_index,
);
if let Some((new_array, is_references)) = new_array {
if is_references {
panic!("References are not supported for array set with dynamic index");
}
let element_type = new_array.type_of_variable.unwrap_array_element_type();
match element_type {
Type::Numeric(_element_type) => {
self.store_variable(&new_array);
}
_ => panic!("Expected NumericType, found {element_type:?}"),
}
if let Some(new_array) = new_array {
self.store_variable(&new_array);
}
}
Instruction::ArrayGetWithConstantIndex { array_index, index, safe_index } => {
// Array index should be limited to 32 bits
// Otherwise it fails at compiler/noirc_evaluator/src/ssa/ir/dfg/simplify.rs:133:40:
let index_32_bits = index & (u32::MAX as usize);
// insert constant index
let index_id = builder.insert_constant(index, NumericType::U32);
let index_id = builder.insert_constant(index_32_bits, NumericType::U32);
let value = self.insert_array_get(
builder,
array_index,
index_id,
/*is constant =*/ true,
safe_index,
);
if let Some((value, _is_references)) = value {
if let Some(value) = value {
self.store_variable(&value);
}
}
Expand All @@ -417,8 +407,11 @@ impl BlockContext {
value_index,
safe_index,
} => {
// Array index should be limited to 32 bits
// Otherwise it fails at compiler/noirc_evaluator/src/ssa/ir/dfg/simplify.rs:133:40:
let index_32_bits = index & (u32::MAX as usize);
// insert constant index
let index_id = builder.insert_constant(index, NumericType::U32);
let index_id = builder.insert_constant(index_32_bits, NumericType::U32);
let new_array = self.insert_array_set(
builder,
array_index,
Expand All @@ -427,34 +420,8 @@ impl BlockContext {
value_index,
safe_index,
);
if let Some((new_array, is_references)) = new_array {
let element_type = match new_array.type_of_variable.clone() {
Type::Array(elements_type, _) => elements_type[0].clone(),
_ => panic!("Expected ArrayType, found {:?}", new_array.type_of_variable),
};
match element_type {
Type::Numeric(_element_type) => {
assert!(
!is_references,
"Encountered numeric element in an array with references"
);
self.store_variable(&new_array);
}
Type::Reference(type_ref) => {
assert!(
is_references,
"Encountered reference element in an array without references"
);
assert!(
type_ref.is_numeric(),
"Expected reference to a numeric type, found {type_ref:?}"
);
self.store_variable(&new_array);
}
_ => {
panic!("Expected NumericType or ReferenceType, found {element_type:?}")
}
}
if let Some(new_array) = new_array {
self.store_variable(&new_array);
}
}
Instruction::FieldToBytesToField { field_idx } => {
Expand Down Expand Up @@ -769,7 +736,7 @@ impl BlockContext {
/// * `safe_index` - If true, the index will be taken modulo the array length
///
/// # Returns
/// * (TypedValue, is_references)
/// * TypedValue
/// * None if the instruction is not enabled or the array is not stored
fn insert_array_get(
&mut self,
Expand All @@ -778,7 +745,7 @@ impl BlockContext {
index: TypedValue,
index_is_constant: bool,
safe_index: bool,
) -> Option<(TypedValue, bool)> {
) -> Option<TypedValue> {
if !self.options.instruction_options.array_get_enabled
|| !self.options.instruction_options.create_array_enabled
{
Expand All @@ -797,7 +764,7 @@ impl BlockContext {
_ => return None,
};
// references are not supported for array get with dynamic index
if array.type_of_variable.is_reference() && !index_is_constant {
if array.type_of_variable.type_contains_reference() && !index_is_constant {
return None;
}
// cast the index to u32
Expand All @@ -808,7 +775,7 @@ impl BlockContext {
array.type_of_variable.unwrap_array_element_type(),
safe_index,
);
Some((value, array.type_of_variable.is_reference()))
Some(value)
}

/// Inserts an array set instruction
Expand All @@ -821,7 +788,7 @@ impl BlockContext {
/// * `safe_index` - If true, the index will be taken modulo the array length
///
/// # Returns
/// * (TypedValue referencing the new array, is_references)
/// * TypedValue referencing the new array
/// * None if the instruction is not enabled or the array is not stored
fn insert_array_set(
&mut self,
Expand All @@ -831,7 +798,7 @@ impl BlockContext {
index_is_constant: bool,
value_index: usize,
safe_index: bool,
) -> Option<(TypedValue, bool)> {
) -> Option<TypedValue> {
if !self.options.instruction_options.array_set_enabled {
return None;
}
Expand All @@ -849,7 +816,7 @@ impl BlockContext {
};

let is_array_of_references =
array.type_of_variable.unwrap_array_element_type().is_reference();
array.type_of_variable.unwrap_array_element_type().type_contains_reference();
// get the array from the stored arrays
// references are not supported for array set with dynamic index
if is_array_of_references && !index_is_constant {
Expand All @@ -863,7 +830,7 @@ impl BlockContext {
};
let new_array =
builder.insert_array_set(array.clone(), index.clone(), value.clone(), safe_index);
Some((new_array, is_array_of_references))
Some(new_array)
}

pub(crate) fn insert_instructions(
Expand Down
16 changes: 14 additions & 2 deletions tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,20 @@ impl FuzzerOutput {
pub(crate) fn compare_results(&self, other: &Self) -> CompareResults {
match (self.is_program_compiled(), other.is_program_compiled()) {
(false, false) => CompareResults::BothFailed,
(true, false) => CompareResults::LeftCompilationFailed,
(false, true) => CompareResults::RightCompilationFailed,
(true, false) => {
if self.get_return_witnesses().is_empty() {
CompareResults::BothFailed
} else {
CompareResults::RightCompilationFailed
}
}
(false, true) => {
if other.get_return_witnesses().is_empty() {
CompareResults::BothFailed
} else {
CompareResults::LeftCompilationFailed
}
}
(true, true) => {
// both programs compiled successfully
let left_return_witnesses = self.get_return_witnesses();
Expand Down
11 changes: 11 additions & 0 deletions tooling/ssa_fuzzer/src/typed_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ impl Type {
matches!(self, Type::Reference(_))
}

pub fn type_contains_reference(&self) -> bool {
match self {
Type::Reference(_) => true,
Type::Array(element_types, _) => {
element_types.iter().any(|t| t.type_contains_reference())
}
Type::Slice(element_types) => element_types.iter().any(|t| t.type_contains_reference()),
Type::Numeric(_) => false,
}
}

pub fn is_array(&self) -> bool {
matches!(self, Type::Array(_, _))
}
Expand Down
Loading