Skip to content

chore: reproduce ACIR-gen ICE on a constant index known only to ACIR gen (AST fuzzer) - #13444

Draft
AztecBot wants to merge 1 commit into
masterfrom
cb/ast-fuzzer-repro-acir-constant-index-ice
Draft

chore: reproduce ACIR-gen ICE on a constant index known only to ACIR gen (AST fuzzer)#13444
AztecBot wants to merge 1 commit into
masterfrom
cb/ast-fuzzer-repro-acir-constant-index-ice

Conversation

@AztecBot

@AztecBot AztecBot commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a load-bearing reproduction (no fix) for the AST fuzzer acir_vs_brillig failure on seed 0xabdfa2be00100000 against master (d89d99a944). This one is a compiler ICE, the most serious of the three seeds from that run.

The bug

ICE: Read resolving to a compile-time constant on memory block b0 which has no preceding write
should be folded at compile time

The reduced program reads an array at an index that is not an SSA constant but is a compile-time constant known only to ACIR gen:

acir(inline) fn main f0 {
  b0(v0: u1):
    v1 = make_array [u1 0, u1 0, u1 1] : [u1; 3]
    constrain u1 0 == v0          ; proves v0 == 0
    v2 = cast v0 as u32
    v3 = unchecked_add v2, u32 2  ; folds to the constant 2 once v0 == 0
    v4 = array_get v1, index v3 -> u1
    return v4
}

v3 is not an SSA numeric constant, so handle_constant_index_wrapper (compiler/noirc_evaluator/src/acir/arrays.rs) — which only checks dfg.get_numeric_constant — falls through to the dynamic memory-op path. But when constrain u1 0 == v0 is lowered, assert_eq_var rewrites v0's witness to the constant 0, and the cast + unchecked_add fold, so the index is the constant 2 in ACIR. ACIR gen then emits a MemoryInit + MemoryOp::Read at a constant index into a block that is never written — exactly the pattern assert_constant_reads_are_folded (compiler/noirc_evaluator/src/acir/mod.rs, added in #13229) rejects, hence the panic.

The reproduction

acir::tests::arrays::constant_index_known_only_to_acir_gen_ices feeds the minimal SSA above through ssa_to_acir_program, which panics on master. It is marked #[should_panic(expected = "ICE: Read resolving to a compile-time constant …")] so it documents the crash deterministically; once ACIR gen consults its own constant tracking (var_to_constant) when choosing the compile-time read path, it stops panicking and the #[should_panic] should be removed.

Severity

High. A hard compiler crash reachable from ordinary source — any program with an index that becomes constant only after a constraint proves an input's value.

Related issues

Refs noir-lang/noir-claude#1558

This PR closes nothing — it is reproduction-only, adds a failing-by-design test, and changes no compiler behaviour, so #1558 stays open after it merges. The closing keyword belongs on the fix PR. (It would not auto-close in any case: GitHub only auto-closes issues in the PR's own repo.)

noir-claude#1558 is the same defect, filed one day before this fuzzer run:

assert_constant_reads_are_folded (noir#13229) aborts every debug and cargo test build of nargo on ordinary safe Noir: handle_constant_index_wrapper declines an index that ACIR's own expression algebra then folds, and read_from_memory has no constant-index fold to catch it

Same assertion, same declining gate (arrays.rs, dfg.get_numeric_constant), same unfolded read_from_memory. It differs only in how the index becomes constant inside ACIR gen: #1558 reaches it by expression-algebra cancellation (a[p0.wrapping_sub(p0)] lowering to (v6 + 2¹²⁸) - v6), this seed by constrain-driven witness substitution. The fix suggested here (consult var_to_constant at the gate) and the one in #1558 (fold in read_from_memory / array_get_value) address the two halves of the same defect. #1558 also reports the AST fuzzer tripping this at ~0.56% of random expression programs, so this seed is very likely one of that population.

Related but distinct: noir-claude#1527 (a different defect in the same #13229 predicated-access machinery this assertion guards) and closed noir-claude#1474 (the sibling debug-only ACIR post-check ICE, since fixed). No open AST Fuzzer issue in this repo covers it.

Full RCA + a suggested fix: https://gist.github.com/AztecBot/c17280a14270f2b29be10177e7b41227


Created by claudebox · group: slackbot · requested by Tom French · Slack thread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant