Repository navigation
fix: two arithmetic overflows in the implode decoder - #1028
Merged
Merged
Conversation
Both panic in debug builds (overflow checks) on crafted entries and wrap in release builds, where the read then fails with an error. read_huffman_code computed the number of code-length bytes as `(byte + 1) as usize` with `byte: u8`. A header byte of 0xff means 256 bytes, which is valid (the literal table has 256 symbols), and overflows the u8 addition. hwzip, which this decoder is ported from, widens first: `num_bytes = (size_t)byte + 1`. HuffmanDecoder::huffman_decode computed the bits left as `length - is.position_in_bits()`. The bit reader can already be past the end of the data when a symbol is decoded (the previous symbol's length is only known after the lookup, and hwzip zero-pads past the end), so the subtraction underflows. Treat no bits left as the end of the stream: return UnexpectedEof, and clamp the second lookup the same way. Tests: a 256-entry code-length table must decode; the Hamlet implode stream truncated at every length must give an error or a prefix of the output, never a panic. Both fail on master.
Pr0methean
approved these changes
Oct 8, 2026
This was referenced Oct 9, 2026
Closed
Closed
Merged
1 task done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two integer overflows in the
legacy-zipimplode decoder (src/legacy/). Both panic in debugbuilds and wrap in release builds, where the read then fails with an error. The PR template asks
for all methods to stay panic-free.
read_huffman_code(implode.rs) computes the number of code-length bytes as(byte + 1) as usizewithbyte: u8. A header byte of 0xff means 256 bytes, which is valid(the literal table has 256 symbols), and
0xff + 1overflows u8:hwzip, which this decoder is ported from, widens first:
num_bytes = (size_t)byte + 1.HuffmanDecoder::huffman_decode(huffman.rs) computes the bits left aslength - is.position_in_bits(). The bit reader can already be past the end of the datawhen a symbol is decoded, so the subtraction underflows:
Reached through
ZipArchiveand through the streaming reader(
read_zipfile_from_stream) on a truncated or crafted imploded entry.Change
num_bytes = usize::from(byte) + 1.huffman_decode, compute the remaining bits withsaturating_sub; when none are left,return an
UnexpectedEoferror (the stream ended in the middle of a symbol). The secondlookup is clamped the same way.
Test
In
src/legacy/implode.rs, next to the existing Hamlet test:code_length_table_with_256_bytes: a 256-entry code-length table (header byte 0xff) mustdecode. Panics on master.
truncated_stream_is_an_error: the Hamlet implode stream truncated at every length mustreturn an error or a prefix of the expected output, never panic. Panics on master at 93 of 249
bytes.
The existing legacy tests pass unchanged. The suite passes on 1.88, stable and nightly with
default features,
--no-default-features,--all-features, and the two single-deflate featuresets;
cargo clippy --all-targets -- -D warnings(default,--no-default-features,--features legacy-zip,--all-features) andcargo doc --no-depsare clean;cargo fmt --check --allis clean.Found with a fuzzer that reads generated archives through the streaming reader.