Skip to content

Add fuzz target for payjoin v2 URI parsing - #1848

Merged
benalleng merged 1 commit into
payjoin:masterfrom
caarloshenriq:feat/fuzz-pjuri-v2
Sep 1, 2026
Merged

Add fuzz target for payjoin v2 URI parsing#1848
benalleng merged 1 commit into
payjoin:masterfrom
caarloshenriq:feat/fuzz-pjuri-v2

Conversation

@caarloshenriq

Copy link
Copy Markdown
Contributor

Adds a libFuzzer target for the v2-specific URI parsing paths in payjoin::Uri, covering the fragment parameters that the existing uri_deserialize_pjuri target never reaches.

What is covered

The v2 pj parameter encodes three required fields in the URL fragment: EX1 (expiration), OH1 (OHTTP keys), and RK1
(receiver HPKE pubkey), each encoded as bech32 without a checksum.

The target exercises:

  • v2::PjParam::parse: validates that all three fields are present and uppercase
  • check_fragment_delimiter: backwards-compatible +/- delimiter handling
  • get_param / set_param: fragment parameter extraction and round-trip reconstruction
  • OhttpKeys::try_from: OHTTP key deserialization
  • HpkePublicKey::from_compressed_bytes: secp256k1 pubkey parsing

Mutator design

Follows the same structure as uri_deserialize_pjuri: a custom mutator preserves a valid bitcoin address and spends the mutation budget on the query. DEFAULT_QUERY seeds the fuzzer with a well-formed v2 pj parameter so it reaches the v2 parsing paths from an empty corpus without needing to construct checksummed or bech32-encoded values by chance. 25% of mutations pass straight to fuzzer_mutate to keep the reject paths and non-UTF-8 handling covered.

Fuzzing results

Run from an empty corpus on x86_64 Linux, 1 fork, 38 seconds:

Metric Value
Coverage counters reached 1767
Feature edges 3762
Corpus size 529 inputs
Crashes / OOM / Timeouts 0 / 0 / 0

Closes part of #1267.

Disclosure: co-authored by Claude

Pull Request Checklist

Please confirm the following before requesting review:

@coveralls

coveralls commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 33417410484

Coverage remained the same at 86.64%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 16474
Covered Lines: 14273
Line Coverage: 86.64%
Coverage Strength: 343.03 hits per line

💛 - Coveralls

@xstoicunicornx

Copy link
Copy Markdown
Collaborator

Looks like needs a rebase.

Covers the v2-specific fragment parameters (EX1, OH1, RK1) that
the existing uri_deserialize_pjuri target never reaches.

A custom mutator seeds the fuzzer with a valid v2 pj parameter so
it reaches the v2 parsing paths from an empty corpus. 25% of
mutations pass straight to fuzzer_mutate to keep the reject paths
covered.

@benalleng benalleng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 40690ca

Looks great!

@benalleng
benalleng merged commit 32c396e into payjoin:master Sep 1, 2026
13 checks passed
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