Skip to content

fix: When only zopfli is available, decompression of deflate should not be possible#348

Merged
Pr0methean merged 2 commits into
zip-rs:masterfrom
darktohka:master
May 12, 2025
Merged

fix: When only zopfli is available, decompression of deflate should not be possible#348
Pr0methean merged 2 commits into
zip-rs:masterfrom
darktohka:master

Conversation

@darktohka

@darktohka darktohka commented May 12, 2025

Copy link
Copy Markdown
Contributor

Fixes #347.

Zopfli is a compression only algorithm. This means that it cannot be used to decompress DEFLATE streams. However, the code currently implies this, and tries to build flate2-related code paths because zopfli sets _deflate_any.

However, unsetting _deflate_any is not enough: zopfli can still compress DEFLATE streams even if it can't decompress them.

So to make sure everything is still OK, allow decompression of DEFLATE only when flate2 is active, but allow compression both when only zopfli is active (in this case, shift the compression level by 9 so the same functionality takes place as when flate2 is enabled), and when both zopfli and flate2 are active (in this case, use flate2 when compression level is less than 9, and zopfli when compression level is higher than 9, as the original intent).

The if cfg!(...) paradigm only works if both conditional blocks can compile regardless of the config options, so instead we must use #[cfg[...]] to compile out the parts that can't compile when flate2 is not available.

As for the compression level ranges:

  • only zopfli: 1-254
  • only flate2: fast-best (1-9)
  • both zopfli and flate2: fast-254 (1-254)
    • flate2 takes place between 1-9
    • zopfli takes place between 10-254

Tests have been modified: some tests require writing DEFLATE zip files as well. Those tests are disabled when DEFLATE can't be compressed, only uncompressed. Two doctests require writing DEFLATE zip files as well, so these doctests are now protected with the config guard.

The CI workflow has also been extended to build two more variants of the crate: one with only flate2 enabled and one with only zopfli enabled.

The CI/CD pipeline builds fine: https://github.com/darktohka/zip2/actions/runs/14960898954

To test this pull request:

  1. git clone https://github.com/darktohka/zip-flate2-zopfli-feature-repro
  2. cd ..
  3. cd zopfli-only-success-fixed
  4. cargo build ==> builds fine

…ot be possible

Signed-off-by: Derzsi Dániel <daniel@tohka.us>

@Pr0methean Pr0methean left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good in principle, but please use the dependency implicit feature to check for flate2, because more than one explicitly-defined feature flag sets it depending on the choice of back end.

Comment thread Cargo.toml Outdated
Comment thread src/compression.rs
pub(crate) enum Decompressor<R: io::BufRead> {
Stored(R),
#[cfg(feature = "_deflate-any")]
#[cfg(feature = "deflate-flate2")]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Change this to feature = "flate2" throughout, so that deflate-zlib will also enable it.

@darktohka darktohka May 12, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It should be fine. deflate-zlib implies the deflate-flate2 feature. Tested with only features = ["deflate-zlib"] set as well.

  1. git clone https://github.com/darktohka/zip-flate2-zopfli-feature-repro
  2. cd zlib-only
  3. cargo build

@darktohka

darktohka commented May 12, 2025

Copy link
Copy Markdown
Contributor Author

Looks good in principle, but please use the dependency implicit feature to check for flate2, because more than one explicitly-defined feature flag sets it depending on the choice of back end.

I don't believe any changes are required. When deflate-flate2 feature is transitively set through another feature (like deflate-zlib) the deflate-flate2 feature is set automatically and the cfg(feature = "deflate-flate2") check is true.

Can you please confirm?

@darktohka darktohka requested a review from Pr0methean May 12, 2025 08:46
@Pr0methean

Copy link
Copy Markdown
Member

@darktohka This looks good.

@Pr0methean Pr0methean enabled auto-merge May 12, 2025 16:57
@Pr0methean Pr0methean added this pull request to the merge queue May 12, 2025
Merged via the queue into zip-rs:master with commit b9a4c5f May 12, 2025
71 checks passed
cosmicexplorer pushed a commit to cosmicexplorer/zip2 that referenced this pull request Sep 30, 2025
…ot be possible (zip-rs#348)

* fix: When only zopfli is available, decompression of deflate should not be possible

Signed-off-by: Derzsi Dániel <daniel@tohka.us>

* fix: Rollback flate2 feature as flate2/rust_backend is enough

---------

Signed-off-by: Derzsi Dániel <daniel@tohka.us>
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.

Build failure when only deflate-zopfli crate feature is enabled

2 participants