test(fuzz): add four coverage-gap targets, seeds, and round-trip asserts #283

Merged
jqueuniet merged 0 commits from refs/pull/283/head into main 2026-07-22 16:48:23 +02:00
jqueuniet commented 2026-07-22 16:42:59 +02:00 (Migrated from codeberg.org)

Closes the fuzz-coverage gaps identified in a review of the existing 23 targets: every top-level container parser was fuzzed, but several deeper decoders were not.

New targets

  • graphics_decode — parses the archive then drains iter_image_with_palette + iter_sfx, driving every record through the on-demand nibble-RLE / bit-plane / overlay image codecs and the SFX codec. graphics_archive stops at the container index and never touches the pixel decoders.
  • sms_smf — the SMF parsers behind resource-fork songs (sms_audio::smf::events, dm2_music::scan_channels). The mac_rsrc targets fuzz only the fork wrapper, not the SMF inside it.
  • cdda — the raw CD-DA LE/BE energy sniffer + sample walker (dm2_music::cdda::{detect_byte_order,to_wav,byte_order_stats}).
  • mod_render — the ProTracker module parser behind mod_audio::LoopRender::new (via xmrs); mod_p41 only covered the depacker.

Round-trip asserts

dungeon_le/be and save_decode_le/be go beyond parse-and-drop to assert writer/parser symmetry: re-parsing their own to_bytes output must re-encode identically. Idempotence, not equality with the fuzzer input (parse accepts non-canonical inputs the writer normalizes). Validated on real fixtures plus 20s of mutation fuzzing each with no counterexample.

ftl_container deliberately keeps no such assert: Ftl::to_bytes repacks payloads contiguously by contract, so a gap-bearing input parses but does not round-trip — confirmed via mutation before reverting the assert (documented inline + in ROADMAP + seeds README).

Seeds

Hand-authored, not game-derived: minimal.mid (MThd + one MTrk) and minimal.mod (M.K. header + one empty pattern) clear the MThd / M.K. magic gates without committing copyrighted, gitignored shipped assets. graphics_decode reuses the graphics_archive corpus; cdda is ungated. Both seeds verified to parse and to raise coverage over blind fuzzing.

Verification

All 27 targets build clean on nightly. Each new target smoke-run (no crashes, growing coverage). Fuzzing remains out of CI (nightly-only, non-terminating), unchanged.

Closes the fuzz-coverage gaps identified in a review of the existing 23 targets: every top-level container parser was fuzzed, but several deeper decoders were not. ## New targets - **`graphics_decode`** — parses the archive then drains `iter_image_with_palette` + `iter_sfx`, driving every record through the on-demand nibble-RLE / bit-plane / overlay image codecs and the SFX codec. `graphics_archive` stops at the container index and never touches the pixel decoders. - **`sms_smf`** — the SMF parsers behind resource-fork songs (`sms_audio::smf::events`, `dm2_music::scan_channels`). The `mac_rsrc` targets fuzz only the fork wrapper, not the SMF inside it. - **`cdda`** — the raw CD-DA LE/BE energy sniffer + sample walker (`dm2_music::cdda::{detect_byte_order,to_wav,byte_order_stats}`). - **`mod_render`** — the ProTracker module parser behind `mod_audio::LoopRender::new` (via `xmrs`); `mod_p41` only covered the depacker. ## Round-trip asserts `dungeon_le/be` and `save_decode_le/be` go beyond parse-and-drop to assert **writer/parser symmetry**: re-parsing their own `to_bytes` output must re-encode identically. Idempotence, not equality with the fuzzer input (parse accepts non-canonical inputs the writer normalizes). Validated on real fixtures plus 20s of mutation fuzzing each with no counterexample. `ftl_container` deliberately keeps **no** such assert: `Ftl::to_bytes` repacks payloads contiguously by contract, so a gap-bearing input parses but does not round-trip — confirmed via mutation before reverting the assert (documented inline + in ROADMAP + seeds README). ## Seeds Hand-authored, not game-derived: `minimal.mid` (MThd + one MTrk) and `minimal.mod` (M.K. header + one empty pattern) clear the MThd / M.K. magic gates without committing copyrighted, gitignored shipped assets. `graphics_decode` reuses the `graphics_archive` corpus; `cdda` is ungated. Both seeds verified to parse and to raise coverage over blind fuzzing. ## Verification All 27 targets build clean on nightly. Each new target smoke-run (no crashes, growing coverage). Fuzzing remains out of CI (nightly-only, non-terminating), unchanged.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jqueuniet/dm2-tools!283
No description provided.