Skip to content

Add fuzz target for ShortId parsing - #1826

Merged
benalleng merged 1 commit into
payjoin:masterfrom
caarloshenriq:feat/fuzz-directory-short-id
Aug 21, 2026
Merged

Add fuzz target for ShortId parsing#1826
benalleng merged 1 commit into
payjoin:masterfrom
caarloshenriq:feat/fuzz-directory-short-id

Conversation

@caarloshenriq

Copy link
Copy Markdown
Contributor

Adds a libFuzzer target for payjoin::directory::ShortId, the 64-bit identifier used in Payjoin Directory URL path segments (/{id}).

What is covered

Three input paths are exercised:

  • TryFrom<&[u8]>: raw 8-byte slices, as stored internally and compared against database keys. Any length other than 8 must be rejected; the target asserts this explicitly.
  • FromStr: attacker-controlled bech32-without-checksum strings, the actual path exercised by payjoin-mailroom when routing incoming requests.
  • Structured mutation (fuzz_near_valid): builds a valid encoding from the input seed, then corrupts it using the remaining bytes as a mutation opcode (truncation, single character substitution, case change, transposition, overlong segment, trailing garbage). This keeps the fuzzer near the parser's acceptance boundary rather than generating inputs that are rejected on the first invalid character.

All three paths assert that a successfully parsed ShortId round-trips through Display/FromStr. Sender and receiver both derive the mailbox URL from this string, so any asymmetry between encoding and decoding would split a session silently.

What is not covered

The network-facing OHTTP/bhttp handling in payjoin-mailroom is out of scope here. Covering those handlers would require adding tokio/axum/hyper to the fuzz crate. The next logical step is fuzzing the session routing and mailbox
matching logic using Arbitrary on payjoin protocol types, pending #1662 and the upstream rust-bitcoin Arbitrary release.

Fuzzing results

Run on x86_64 Linux, 6 forks (nproc - 2), 305 seconds:

Metric Value
Total executions ~83.7M
Coverage counters reached 280 / 1345
Feature edges 875
Corpus size 151 inputs
Crashes / OOM / Timeouts 0 / 0 / 0

Coverage saturated at ~72s and held stable through the remaining ~230s, confirming the reachable space for this parser is fully explored. The target's value going forward is regression detection: any change to ShortId, bech32::nochecksum, or the Display/FromStr contract will surface here before reaching CI.

Addresses part of #1267.

Disclosure: co-authored by Claude

Pull Request Checklist

Please confirm the following before requesting review:

@coveralls

coveralls commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 32400373640

Coverage remained the same at 86.718%

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: 16458
Covered Lines: 14272
Line Coverage: 86.72%
Coverage Strength: 343.65 hits per line

💛 - Coveralls

benalleng
benalleng previously approved these changes Aug 20, 2026

@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.

TACK 7200876

directory_short_id
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1601642367
...
#4741050: cov: 280 ft: 874 corp: 156 exec/s: 139574 oom/timeout/crash: 0/0/0 time: 37s job: 7 dft_time: 0
INFO: fuzzed for 37 seconds, wrapping up soon

Comment thread fuzz/fuzz_targets/directory/short_id.rs Outdated
Add a libFuzzer target covering payjoin::directory::ShortId, the
64-bit identifier used in Payjoin Directory URL path segments.

The target exercises three paths: TryFrom<&[u8]> on raw 8-byte
slices, FromStr on attacker-controlled bech32 strings as seen by
payjoin-mailroom when routing /{id} requests, and a structured
mutation path that corrupts known-good encodings (truncation,
character substitution, case change, transposition, overlong
input, trailing garbage) to keep the fuzzer near the parser's
acceptance boundary.

All three paths assert that a successfully parsed ShortId
round-trips through Display/FromStr, since sender and receiver
depend on that round-trip to agree on a session's mailbox.

Addresses part of the payjoin directory fuzzing candidate in
payjoin#1267. The network-facing OHTTP/bhttp handling in
payjoin-mailroom is left for a follow-up pending discussion on
the intended scope of that item.

@erickcestari erickcestari left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@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 8f4aad6

@benalleng
benalleng merged commit a9fbc0b into payjoin:master Aug 21, 2026
13 checks passed
@caarloshenriq
caarloshenriq deleted the feat/fuzz-directory-short-id branch August 21, 2026 12:44
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