Skip to content

feat: reject ZIP archives with unsupported Deflate64 compression up front#157

Merged
otavio merged 1 commit intomasterfrom
feat/deflate64-preflight
Apr 22, 2026
Merged

feat: reject ZIP archives with unsupported Deflate64 compression up front#157
otavio merged 1 commit intomasterfrom
feat/deflate64-preflight

Conversation

@otavio
Copy link
Copy Markdown
Member

@otavio otavio commented Apr 22, 2026

Summary

  • Adds a ZIP central-directory preflight that scans entries for compression methods libarchive cannot decode (currently just Deflate64 / method 9) and fails fast with a new Error::UnsupportedZipCompression(Vec<(String, u16)>) listing the offending entries.
  • Wires the preflight into list_archive_files, uncompress_archive, uncompress_archive_file, and ArchiveIterator so the error surfaces before libarchive aborts mid-stream with Unsupported ZIP compression method (9: deflation-64-bit).
  • Replaces AsyncReadWrapper::seek's unreachable!() with ErrorKind::Unsupported so the preflight degrades gracefully on unseekable async readers (channel-fed wrappers) instead of panicking.

Closes #136.

Design notes

  • Hand-rolled central-directory parser (~160 LOC, no new deps). Parses classic EOCD and Zip64 EOCD/locator, reads the whole CD in one shot for O(1) syscalls per archive, caps allocation at 16 MiB so a malformed/hostile file can't OOM us. Non-ZIP inputs, malformed ZIPs, and unseekable readers all fall through so libarchive keeps its normal behavior — we only intercept when we are sure the archive contains an unsupported method.
  • Error variant is structured (Vec<(String, u16)>) rather than a formatted Error::Extraction(String), so callers can pattern-match on offending entries and their method numbers.
  • Encryption is intentionally not flagged. libarchive can decrypt ZIP entries via archive_read_add_passphrase; Support encryption? #82 tracks exposing that from this crate. Blocking encrypted entries now would preempt that work. A comment in is_unsupported_method documents the decision.

Test plan

  • New regression tests covering the three public entry points (list_archive_files, uncompress_archive, ArchiveIterator::from_read) on a Deflate64 fixture, plus a guard that plain-Deflate (method 8) archives remain unaffected.
  • All 39 existing integration tests pass (including the 10 async ones — they exercise the new AsyncReadWrapper::seek fallback path).
  • cargo clippy --all-targets clean with default and async features.

Fixture

tests/fixtures/deflate64.zip (229 B) — generated with 7z a -tzip -mm=Deflate64 over a repeated-string payload large enough that 7-Zip actually picks Deflate64 instead of Store. Confirmed Method = Deflate64 via 7z l -slt.

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 22, 2026

Coverage Report for CI Build 24793702738

Coverage increased (+0.09%) to 76.947%

Details

  • Coverage increased (+0.09%) from the base build.
  • Patch coverage: 34 uncovered changes across 2 files (113 of 147 lines covered, 76.87%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
src/zip_preflight.rs 111 80 72.07%
tests/integration_test.rs 29 26 89.66%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1900
Covered Lines: 1462
Line Coverage: 76.95%
Coverage Strength: 58.08 hits per line

💛 - Coveralls

@otavio otavio force-pushed the feat/deflate64-preflight branch from 2cd4cd4 to fb80897 Compare April 22, 2026 17:39
…ront

- Add a central-directory preflight that scans ZIP entries for methods libarchive
  cannot decode (currently Deflate64 / method 9) and fails fast with a new
  Error::UnsupportedZipCompression listing the offending entries
- Wire the preflight into list_archive_files, uncompress_archive, and
  ArchiveIterator so the error surfaces before libarchive aborts mid-stream
- Replace AsyncReadWrapper::seek's unreachable!() with ErrorKind::Unsupported
  so the preflight degrades gracefully on unseekable async readers
- Cover the behavior with regression tests and a Deflate64 fixture
- Note the change in CHANGES.md

Closes #136
@otavio otavio force-pushed the feat/deflate64-preflight branch from fb80897 to 802f79c Compare April 22, 2026 17:49
@otavio otavio merged commit 3303e9e into master Apr 22, 2026
14 checks passed
@otavio otavio deleted the feat/deflate64-preflight branch April 22, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Extraction error: 'Unsupported ZIP compression method (9: deflation-64-bit)'

2 participants