Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
ac0bf6e
Skeleton of an SSA interpreter based fuzz target
aakoshh May 9, 2025
828ff75
Make SSA interpreter parts public
aakoshh May 9, 2025
f8e2a26
Make results generic. Add interpreted results
aakoshh May 9, 2025
5b2b12f
Map ABI input to SSA
aakoshh May 9, 2025
3b730c6
Add cargo fuzz target
aakoshh May 9, 2025
3879323
Build the inputs from the SSA
aakoshh May 9, 2025
9e588d8
Remove println
aakoshh May 9, 2025
ec4b77e
Print SSA inputs
aakoshh May 12, 2025
97e446d
Fix negative int handling in the interpreter
aakoshh May 12, 2025
38e18b7
Map ABI types into specific numeric value
aakoshh May 12, 2025
d81213d
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 12, 2025
3b96985
Ignore value IDs in error comparison
aakoshh May 12, 2025
43e91b6
Fix SSA input formatting
aakoshh May 12, 2025
c233781
Pass tuples as separate values
aakoshh May 12, 2025
1e08d6d
Fix negative int conversion to Field in the interpreter
aakoshh May 12, 2025
a8a3801
Flatten tuples wherever they are
aakoshh May 12, 2025
44c403f
Use Comparable::equivalent for results as well as error
aakoshh May 12, 2025
3608983
Allow shifting u1
aakoshh May 12, 2025
4b66ef3
Comparable to recurse into the element
aakoshh May 12, 2025
b219fc0
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 12, 2025
b354cea
Avoid call_data parameters for now
aakoshh May 12, 2025
c0013f2
Allow arithmetic operations on u1 in the interpreter
aakoshh May 12, 2025
5a1fbfd
Add u1 ops to interpreter
jfecher May 12, 2025
7464b68
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 12, 2025
a152bd1
Revert "Avoid call_data parameters for now"
aakoshh May 12, 2025
8ae03c7
Fix clippy
aakoshh May 12, 2025
5074639
Add ticket number to TODO
aakoshh May 12, 2025
77d3d39
Use IntegerConstant
jfecher May 13, 2025
0e932a4
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 13, 2025
09e8403
Add test that shows the SSA failure on casting
aakoshh May 13, 2025
b26ac04
Merge remote-tracking branch 'origin/master' into jf/interpreter-addi…
aakoshh May 13, 2025
309075b
Fix odd cast semantics
jfecher May 13, 2025
51f928f
Merge branch 'jf/interpreter-additions' of https://github.com/noir-la…
jfecher May 13, 2025
3d9fedd
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 13, 2025
a943b98
Fix cast behavior... again
jfecher May 13, 2025
b4dede8
Remove accidental printlns
jfecher May 13, 2025
d78a113
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 13, 2025
fc98481
Add test that shows wrong value returned by the SSA interpreter
aakoshh May 13, 2025
2b1b9e9
Use log::debug! for printing stuff up front
aakoshh May 14, 2025
02e4f4d
Compare the details in Overflows
aakoshh May 14, 2025
caead66
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 14, 2025
6c76d5c
'fix' casting and truncate
jfecher May 14, 2025
25ee60e
Merge branch 'master' into jf/interpreter-additions
jfecher May 14, 2025
fdbeed9
New test on master needed to be updated
jfecher May 14, 2025
5c573bd
Merge remote-tracking branch 'origin/jf/interpreter-additions' into a…
aakoshh May 15, 2025
14b4487
Fix clippy
aakoshh May 15, 2025
5441875
Merge remote-tracking branch 'origin/master' into af/8413-ast-fuzz-pr…
aakoshh May 15, 2025
eddf15e
Fix merge
aakoshh May 15, 2025
bb532cc
Enable fuzzing morphs and the SSA interpreter on CI
aakoshh May 15, 2025
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: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ arbitrary = "1.4.1"
arbtest = "0.3.2"
cfg-if = "1.0.0"
dirs = "4"
env_logger = "0.11.6"
log = "0.4"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0"
smol_str = { version = "0.3.2", features = ["serde"] }
Expand Down
8 changes: 4 additions & 4 deletions compiler/noirc_evaluator/src/ssa/interpreter/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use thiserror::Error;

pub(super) const MAX_UNSIGNED_BIT_SIZE: u32 = 128;

#[derive(Debug, Error)]
pub(crate) enum InterpreterError {
#[derive(Debug, Error, PartialEq, Eq)]
pub enum InterpreterError {
/// These errors are all the result from malformed input SSA
#[error("{0}")]
Internal(InternalError),
Expand Down Expand Up @@ -61,8 +61,8 @@ pub(crate) enum InterpreterError {
}

/// These errors can only result from interpreting malformed SSA
#[derive(Debug, Error)]
pub(crate) enum InternalError {
#[derive(Debug, Error, PartialEq, Eq)]
pub enum InternalError {
#[error(
"Argument count {arguments} to block {block} does not match the expected parameter count {parameters}"
)]
Expand Down
5 changes: 3 additions & 2 deletions compiler/noirc_evaluator/src/ssa/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use iter_extended::{try_vecmap, vecmap};
use noirc_frontend::Shared;
use value::{ArrayValue, NumericValue, ReferenceValue};

mod errors;
pub mod errors;
mod intrinsics;
mod tests;
pub mod value;
Expand Down Expand Up @@ -63,7 +63,7 @@ type IResults = IResult<Vec<Value>>;

#[allow(unused)]
impl Ssa {
pub(crate) fn interpret(&self, args: Vec<Value>) -> IResults {
pub fn interpret(&self, args: Vec<Value>) -> IResults {
self.interpret_function(self.main_id, args)
}

Expand Down Expand Up @@ -111,6 +111,7 @@ impl<'ssa> Interpreter<'ssa> {
/// Define or redefine a value.
/// Redefinitions are expected in the case of loops.
fn define(&mut self, id: ValueId, value: Value) {
eprintln!("{id} := {value}");
self.call_context_mut().scope.insert(id, value);
}

Expand Down
10 changes: 5 additions & 5 deletions compiler/noirc_evaluator/src/ssa/interpreter/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::ssa::ir::{
use super::IResult;

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Value {
pub enum Value {
Numeric(NumericValue),
Reference(ReferenceValue),
ArrayOrSlice(ArrayValue),
Expand All @@ -24,7 +24,7 @@ pub(crate) enum Value {
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum NumericValue {
pub enum NumericValue {
Field(FieldElement),

U1(bool),
Expand All @@ -41,7 +41,7 @@ pub(crate) enum NumericValue {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ReferenceValue {
pub struct ReferenceValue {
/// This is included mostly for debugging to distinguish different
/// ReferenceValues which store the same element.
pub original_id: ValueId,
Expand All @@ -53,7 +53,7 @@ pub(crate) struct ReferenceValue {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ArrayValue {
pub struct ArrayValue {
pub elements: Shared<Vec<Value>>,

/// The `Shared` type contains its own reference count but we need to track
Expand Down Expand Up @@ -244,7 +244,7 @@ impl NumericValue {
}
}

pub(crate) fn from_constant(constant: FieldElement, typ: NumericType) -> IResult<NumericValue> {
pub fn from_constant(constant: FieldElement, typ: NumericType) -> IResult<NumericValue> {
use super::InternalError::{ConstantDoesNotFitInType, UnsupportedNumericType};
use super::InterpreterError::Internal;

Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_evaluator/src/ssa/ir/integer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl IntegerConstant {
.map(|value| Self::Signed { value, bit_size })
}
NumericType::Unsigned { bit_size } => {
Some(Self::Unsigned { value: field.to_u128(), bit_size })
field.try_into_u128().map(|value| Self::Unsigned { value, bit_size })
}
NumericType::NativeField => None,
}
Expand Down
5 changes: 1 addition & 4 deletions compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ pub struct Ssa {
impl Ssa {
/// Create a new Ssa object from the given SSA functions.
/// The first function in this vector is expected to be the main function.
pub(crate) fn new(
functions: Vec<Function>,
error_types: BTreeMap<ErrorSelector, HirType>,
) -> Self {
pub fn new(functions: Vec<Function>, error_types: BTreeMap<ErrorSelector, HirType>) -> Self {
let main_id = functions.first().expect("Expected at least 1 SSA function").id();
let mut max_id = main_id;

Expand Down
6 changes: 5 additions & 1 deletion tooling/ast_fuzzer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,22 @@ color-eyre.workspace = true
im.workspace = true
proptest.workspace = true
strum.workspace = true
rand.workspace = true
regex.workspace = true
log.workspace = true

acir.workspace = true
acvm.workspace = true
bn254_blackbox_solver.workspace = true
iter-extended.workspace = true
nargo.workspace = true
noirc_abi.workspace = true
noirc_driver.workspace = true
noirc_evaluator.workspace = true
noirc_frontend.workspace = true
noir_greybox_fuzzer.workspace = true
rand.workspace = true

[dev-dependencies]
arbtest.workspace = true
insta.workspace = true
similar-asserts.workspace = true
9 changes: 9 additions & 0 deletions tooling/ast_fuzzer/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ noir_ast_fuzzer = { path = ".." }

[dev-dependencies]
arbtest.workspace = true
env_logger.workspace = true


[[bin]]
name = "min_vs_full"
Expand Down Expand Up @@ -53,3 +55,10 @@ path = "fuzz_targets/orig_vs_morph.rs"
test = false
doc = false
bench = false

[[bin]]
name = "pass_vs_prev"
path = "fuzz_targets/pass_vs_prev.rs"
test = false
doc = false
bench = false
12 changes: 12 additions & 0 deletions tooling/ast_fuzzer/fuzz/fuzz_targets/pass_vs_prev.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! ```text
//! cargo +nightly fuzz run pass_vs_prev -- -runs=10000 -max_len=1048576 -len_control=0
//! ```
#![no_main]

use libfuzzer_sys::arbitrary::Unstructured;
use libfuzzer_sys::fuzz_target;
use noir_ast_fuzzer_fuzz::targets::pass_vs_prev;

fuzz_target!(|data: &[u8]| {
pass_vs_prev::fuzz(&mut Unstructured::new(data)).unwrap();
});
65 changes: 62 additions & 3 deletions tooling/ast_fuzzer/fuzz/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use acir::circuit::ExpressionWidth;
use color_eyre::eyre;
use noir_ast_fuzzer::DisplayAstAsNoir;
use noir_ast_fuzzer::compare::{CompareCompiled, CompareComptime, CompareResult, HasPrograms};
use noir_ast_fuzzer::compare::{
CompareCompiled, CompareCompiledResult, CompareComptime, CompareInterpreted,
CompareInterpretedResult, HasPrograms,
};
use noirc_abi::input_parser::Format;
use noirc_evaluator::brillig::Brillig;
use noirc_evaluator::ssa::{SsaPass, primary_passes, secondary_passes};
Expand Down Expand Up @@ -79,7 +82,10 @@ where
}

/// Compare the execution result and print the inputs if the result is a failure.
pub fn compare_results<P>(inputs: &CompareCompiled<P>, result: &CompareResult) -> eyre::Result<()>
pub fn compare_results_compiled<P>(
inputs: &CompareCompiled<P>,
result: &CompareCompiledResult,
) -> eyre::Result<()>
where
CompareCompiled<P>: HasPrograms,
{
Expand Down Expand Up @@ -122,7 +128,7 @@ where
/// Compare the execution result for comptime fuzzing and print the inputs if the result is a failure.
pub fn compare_results_comptime(
inputs: &CompareComptime,
result: &CompareResult,
result: &CompareCompiledResult,
) -> eyre::Result<()> {
let res = result.return_value_or_err();

Expand All @@ -143,3 +149,56 @@ pub fn compare_results_comptime(
Ok(())
}
}

/// Compare the execution result and print the inputs if the result is a failure.
pub fn compare_results_interpreted(
inputs: &CompareInterpreted,
result: &CompareInterpretedResult,
) -> eyre::Result<()> {
let res = result.return_value_or_err();

if let Err(report) = res {
eprintln!("---\nComparison failed:");
eprintln!("{report:#}");

// Showing the AST as Noir so we can easily create integration tests.
eprintln!("---\nAST:\n{}", DisplayAstAsNoir(&inputs.program));

// Showing the inputs as TOML so we can easily create a Prover.toml file.
eprintln!(
"---\nABI Inputs:\n{}",
Format::Toml
.serialize(&inputs.input_map, &inputs.abi)
.unwrap_or_else(|e| format!("failed to serialize inputs: {e}"))
);

// Show the SSA inputs as well so we can see any discrepancy in encoding.
eprintln!(
"---\nSSA Inputs:\n{}",
inputs
.input_values
.iter()
.enumerate()
.map(|(i, v)| format!("{i}: {v}"))
.collect::<Vec<_>>()
.join("\n")
);

// Common options for the SSA passes.
eprintln!("---\nOptions:\n{:?}", inputs.options);

eprintln!(
"---\nSSA 1 after step {} ({}):\n{}",
inputs.ssa1.step, inputs.ssa1.msg, inputs.ssa1.ssa
);
eprintln!(
"---\nSSA 2 after step {} ({}):\n{}",
inputs.ssa2.step, inputs.ssa2.msg, inputs.ssa2.ssa
);

// Returning it as-is, so we can see the error message at the bottom as well.
Err(report)
} else {
Ok(())
}
}
9 changes: 7 additions & 2 deletions tooling/ast_fuzzer/fuzz/src/targets/acir_vs_brillig.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Compare the execution of random ASTs between the normal execution
//! vs when everything is forced to be Brillig.
use crate::{compare_results, create_ssa_or_die, default_ssa_options};
use crate::{compare_results_compiled, create_ssa_or_die, default_ssa_options};
use arbitrary::Arbitrary;
use arbitrary::Unstructured;
use color_eyre::eyre;
Expand Down Expand Up @@ -41,11 +41,12 @@ pub fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {

let result = inputs.exec()?;

compare_results(&inputs, &result)
compare_results_compiled(&inputs, &result)
}

#[cfg(test)]
mod tests {
use crate::targets::tests::is_running_in_ci;

/// ```ignore
/// NOIR_ARBTEST_SEED=0x6819c61400001000 \
Expand All @@ -54,6 +55,10 @@ mod tests {
/// ```
#[test]
fn fuzz_with_arbtest() {
if is_running_in_ci() {
// TODO: Investigate stack overflow and disagreements.
return;
}
crate::targets::tests::fuzz_with_arbtest(super::fuzz);
}
}
5 changes: 5 additions & 0 deletions tooling/ast_fuzzer/fuzz/src/targets/comptime_vs_brillig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {

#[cfg(test)]
mod tests {
use crate::targets::tests::is_running_in_ci;

/// ```ignore
/// NOIR_ARBTEST_SEED=0x6819c61400001000 \
Expand All @@ -58,6 +59,10 @@ mod tests {
/// ```
#[test]
fn fuzz_with_arbtest() {
if is_running_in_ci() {
// #8511
return;
}
crate::targets::tests::fuzz_with_arbtest(super::fuzz);
}
}
10 changes: 8 additions & 2 deletions tooling/ast_fuzzer/fuzz/src/targets/min_vs_full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! (or as close as we can stay to the initial state)
//! and the fully optimized version.
use crate::{
compare_results, create_ssa_or_die, create_ssa_with_passes_or_die, default_ssa_options,
compare_results_compiled, create_ssa_or_die, create_ssa_with_passes_or_die, default_ssa_options,
};
use arbitrary::{Arbitrary, Unstructured};
use color_eyre::eyre;
Expand Down Expand Up @@ -55,19 +55,25 @@ pub fn fuzz(u: &mut Unstructured) -> eyre::Result<()> {
if matches!(result, CompareResult::BothFailed(_, _) | CompareResult::LeftFailed(_, _)) {
Ok(())
} else {
compare_results(&inputs, &result)
compare_results_compiled(&inputs, &result)
}
}

#[cfg(test)]
mod tests {
use crate::targets::tests::is_running_in_ci;

/// ```ignore
/// NOIR_ARBTEST_SEED=0x6819c61400001000 \
/// NOIR_AST_FUZZER_SHOW_AST=1 \
/// cargo test -p noir_ast_fuzzer_fuzz min_vs_full
/// ```
#[test]
fn fuzz_with_arbtest() {
if is_running_in_ci() {
// TODO: Investigate second program constraint failures.
return;
}
crate::targets::tests::fuzz_with_arbtest(super::fuzz);
}
}
Loading
Loading