Skip to content

fix(stark): reject truncated deep_poly_openings instead of panicking#783

Merged
MauroToscano merged 1 commit into
mainfrom
fix/verifier-deep-openings-panic
Jul 6, 2026
Merged

fix(stark): reject truncated deep_poly_openings instead of panicking#783
MauroToscano merged 1 commit into
mainfrom
fix/verifier-deep-openings-panic

Conversation

@MauroToscano

Copy link
Copy Markdown
Contributor

Summary

The STARK verifier panics with an out-of-bounds index (rather than returning false) when handed a malformed proof whose deep_poly_openings Vec is shorter than the FRI query count. This is a verifier-DoS on malicious input.

reconstruct_deep_composition_poly_evaluations_for_all_queries indexes proof.deep_poly_openings[i] for every i in 0..fri_number_of_queries, but that Vec's length is never checked. The only length guard in the verify path (proof.query_list.len() < fri_number_of_queries) validates a different field. A prover that keeps query_list at full length but truncates deep_poly_openings sails through Fiat-Shamir replay, grinding, and step 2, then triggers index out of bounds at verifier.rs:552.

Fix

Add a length guard at the top of the reconstruct helper (it already returns Option, so None cleanly rejects), mirroring the existing query_list guard. Extra entries stay harmless (never indexed), matching the < convention of that guard.

Test

test_verify_rejects_truncated_deep_poly_openings builds a valid proof, drops one opening, and asserts the verifier returns false without panicking. Verified to have teeth: it panics at verifier.rs:552 (index out of bounds: the len is 2 but the index is 2) against the unpatched verifier, and passes with the guard. Full small_trace_tests module green; cargo fmt --check and clippy -p stark clean.

Context

Found while reviewing #729 (FRI early termination). The bug is pre-existing on main, independent of that PR, so it is fixed here as a standalone hotfix rather than bundled into the feature branch. #729 adds structural length checks for exactly this class of untrusted-Vec-length bug on sibling fields; this closes the remaining one on deep_poly_openings.

reconstruct_deep_composition_poly_evaluations_for_all_queries indexes
deep_poly_openings[i] for every FRI query index (0..fri_number_of_queries),
but that Vec's length is never pinned — the only length guard in the verify
path checks the separate query_list field. A malicious proof that keeps
query_list intact but truncates deep_poly_openings makes the verifier panic
with an out-of-bounds index instead of returning false (verifier DoS).

Add a length guard at the top of the reconstruct helper (it already returns
Option, so None cleanly rejects), mirroring the existing query_list guard.
Add a negative test that truncates deep_poly_openings and asserts the
verifier rejects without panicking.
@MauroToscano MauroToscano enabled auto-merge July 6, 2026 18:54
@MauroToscano MauroToscano added this pull request to the merge queue Jul 6, 2026
Merged via the queue into main with commit 4f29b70 Jul 6, 2026
15 checks passed
@MauroToscano MauroToscano deleted the fix/verifier-deep-openings-panic branch July 6, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants