Skip to content

test(fuzz): add dedicated fuzz targets for rar2/rar3/rar5 - #120

Merged
MagicalTux merged 1 commit into
KarpelesLab:masterfrom
jdlien:rar-fuzz-targets
Aug 16, 2026
Merged

test(fuzz): add dedicated fuzz targets for rar2/rar3/rar5#120
MagicalTux merged 1 commit into
KarpelesLab:masterfrom
jdlien:rar-fuzz-targets

Conversation

@jdlien

@jdlien jdlien commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

CONTRIBUTING says every decoder gets a fuzz target, but the RAR decoders only had coverage via decoder_dispatch. This adds dedicated decoder_rar2/rar3/rar5 targets following the existing pattern (loop-guard, out-of-band params derived from an input prefix — unpack size capped at 1 MiB, rar5 window capped at 4 MiB). Registered in fuzz/Cargo.toml and the fuzz.yml matrix.

Smoke-ran each ~10 min locally (nightly + cargo-fuzz): no crashes/OOMs/timeouts.

@jdlien
jdlien force-pushed the rar-fuzz-targets branch from ef11c8d to ef71da0 Compare July 16, 2026 16:42
@MagicalTux MagicalTux closed this Aug 16, 2026
@MagicalTux MagicalTux reopened this Aug 16, 2026
MagicalTux pushed a commit to jdlien/compcol that referenced this pull request Aug 16, 2026
…ta fixtures

Review findings on the in-band filter implementation, all three fixed by
moving to incremental filter application (flush_completed_filters):

- A slot-0 filter-table reset now applies the completed-window prefix and
  cancels everything still pending, mirroring unrar's InitFilters — a
  canceled filter must never rewrite output. Previously pending filters
  survived the reset and ran at finish.
- The pending queue is capped at 8192 concurrent filters (unrar's
  MAX_UNPACK_FILTERS); when the cap is hit after draining completed
  windows the stream is rejected as corrupt.
- A filter window the stream never finishes producing is now Corrupt
  instead of silently returning pre-filter bytes as success. (unrar
  writes the raw bytes and relies on the container CRC to flag the file;
  surfacing the error directly matches this crate's malformed-input
  policy.)

Flushing is prefix-only — a completed window queued behind an incomplete
one waits — so overlapping windows (filter chains) always apply in
declaration order. Output is append-only and LZ back-references read the
unfiltered window, so early application is equivalent to end-of-stream
application.

New coverage:
- Declaration-level unit tests (reset/cancel semantics, the cap,
  slot-reuse remembered lengths, prefix ordering, truncated-window
  integration test) driving the parser with the real 29-byte Delta
  program.
- rar5 end-to-end real-archive fixtures: a Delta-filtered member run and
  a whole six-member solid group exercising add_file_boundary against
  the archives' own data-CRCs, plus a regression guard showing exactly
  the x86 member corrupts when boundaries are not registered.
- Both fuzz targets from the rar-fuzz-targets branch (KarpelesLab#120) merge-tested
  against this branch and run under ASan seeded with corpus payloads:
  decoder_rar3 328k runs / decoder_rar5 341k runs, no findings.

Docs: README capability matrix updated for both formats; rar5 module
docs now describe Delta support and the solid-group calling convention.

Known gap, documented: the 57-byte E8E9 program has no real-archive
fixture because no current archiver emits it (rar 6.24 uses the E8-only
program); its fingerprint cites libarchive and the transform is
unit-tested.
MagicalTux pushed a commit to jdlien/compcol that referenced this pull request Aug 16, 2026
…ta fixtures

Review findings on the in-band filter implementation, all three fixed by
moving to incremental filter application (flush_completed_filters):

- A slot-0 filter-table reset now applies the completed-window prefix and
  cancels everything still pending, mirroring unrar's InitFilters — a
  canceled filter must never rewrite output. Previously pending filters
  survived the reset and ran at finish.
- The pending queue is capped at 8192 concurrent filters (unrar's
  MAX_UNPACK_FILTERS); when the cap is hit after draining completed
  windows the stream is rejected as corrupt.
- A filter window the stream never finishes producing is now Corrupt
  instead of silently returning pre-filter bytes as success. (unrar
  writes the raw bytes and relies on the container CRC to flag the file;
  surfacing the error directly matches this crate's malformed-input
  policy.)

Flushing is prefix-only — a completed window queued behind an incomplete
one waits — so overlapping windows (filter chains) always apply in
declaration order. Output is append-only and LZ back-references read the
unfiltered window, so early application is equivalent to end-of-stream
application.

New coverage:
- Declaration-level unit tests (reset/cancel semantics, the cap,
  slot-reuse remembered lengths, prefix ordering, truncated-window
  integration test) driving the parser with the real 29-byte Delta
  program.
- rar5 end-to-end real-archive fixtures: a Delta-filtered member run and
  a whole six-member solid group exercising add_file_boundary against
  the archives' own data-CRCs, plus a regression guard showing exactly
  the x86 member corrupts when boundaries are not registered.
- Both fuzz targets from the rar-fuzz-targets branch (KarpelesLab#120) merge-tested
  against this branch and run under ASan seeded with corpus payloads:
  decoder_rar3 328k runs / decoder_rar5 341k runs, no findings.

Docs: README capability matrix updated for both formats; rar5 module
docs now describe Delta support and the solid-group calling convention.

Known gap, documented: the 57-byte E8E9 program has no real-archive
fixture because no current archiver emits it (rar 6.24 uses the E8-only
program); its fingerprint cites libarchive and the transform is
unit-tested.
CONTRIBUTING promises every decoder a fuzz target, but the RAR decoders
were only reachable through decoder_dispatch. Add one each, house pattern.
Since RAR streams do not self-delimit, each derives out-of-band params from
an input prefix (unpack size, rar3 E8 flag, rar5 window selector), capped at
1 MiB / 4 MiB so the fuzzer explores without gigabyte allocations. Registered
in fuzz/Cargo.toml and the fuzz.yml matrix.
@MagicalTux
MagicalTux merged commit f2020df into KarpelesLab:master Aug 16, 2026
46 checks passed
@MagicalTux MagicalTux mentioned this pull request Aug 16, 2026
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.

2 participants