Repository navigation
fix(core): reject malformed multi-proofs instead of panicking - #959
Merged
rphmeier merged 1 commit intoOct 23, 2026
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
proof::verify_multi_proofpanics on malformed input.verify_rangetrusts three things taken straight from the proof (MultiPathProof.depth, the terminal path lengths and the number of siblings) and slices with them unchecked. Proofs come from untrusted parties andMultiProofis deserializable (serde/borsh), so anyone who can submit a proof can crash the verifier.Found from #958
Fix
verifynow validates the structure before callingverify_range:depth <= terminal.path().len(), elseInvalidDepth.PathPrefixOfAnother. For sorted paths, checking neighbours is enough. This guaranteesstart_depth <= depth <= path.len()andcommon_len < 256everywhere inverify_range, which removes the oldTODO.verify_rangechecks that enough siblings remain before slicing, at a terminal and at a bisection, elseTooFewSiblings.Honest proofs always satisfy these conditions, so their behaviour is unchanged.
API impact
This adds three variants to
MultiProofVerificationError:TooFewSiblings,InvalidDepthandPathPrefixOfAnother. The enum is not#[non_exhaustive], so downstream code that matches it exhaustively will stop compiling. Nothing in this repo matches it. If this needs to ship as a patch release, the alternative is to map these cases onto existing variants and give up the precise error.Testing
multi_proof.rs(verify_rejects_depth_beyond_terminal_path,verify_rejects_path_prefix_of_another,verify_rejects_too_few_siblings), covering each new check at both the terminal and the bisection level. All three panicked inverify_rangebefore the fix.cargo test -p nomt -p nomt-coreon Linux (io_uring): 278 passed, 0 failed.proof_verifycorpus replay without a crash.proof_verifyrun, 10 min, 8 workers: pending🤖 Generated with Claude Code