Fix LZMA dictionary size parsing in 7z archives (read 4 bytes instead of 3)#61
Open
analytical-engines wants to merge 1 commit intotsolomko:developfrom
Open
Conversation
The LZMA dictionary size was being read from only 3 bytes (indices 1-3) instead of the full 4 bytes (indices 1-4) specified in the LZMA format. This caused decompression to fail with LZMAError.notEnoughToRepeat for archives using dictionary sizes >= 16MB (e.g., LZMA:24 = 2^24 = 16MB), because the high byte was not read and the dictionary size defaulted to the minimum 4096 bytes. Change: `for i in 1..<4` → `for i in 1..<5`
fad4e5f to
33341b6
Compare
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.
Report: LZMA dictionary size incorrectly parsed (only 3 bytes read instead of 4)
Summary
In 7zFolder.swift, the LZMA dictionary size is read using only 3 bytes instead of 4, causing decompression to fail with LZMAError.notEnoughToRepeat for archives with dictionary sizes >= 16MB.
Environment
Steps to Reproduce
Expected Behavior
Archive should decompress successfully, as it does with the official 7z command-line tool and other applications.
Actual Behavior
Decompression fails with LZMAError.notEnoughToRepeat.
Root Cause
In Sources/7-Zip/7zFolder.swift, lines 174-176:
The loop 1..<4 only iterates over indices [1, 2, 3], reading 3 bytes. However, the LZMA dictionary size is stored as a 4-byte little-endian integer in properties[1...4].
For a dictionary size of 16MB (0x01000000 in little-endian):
properties[1] = 0x00
properties[2] = 0x00
properties[3] = 0x00
properties[4] = 0x01 ← Not read!
Result: dictionarySize is computed as 0, then adjusted to the minimum 4096 bytes by LZMAProperties. The decoder allocates a 4KB dictionary instead of the required 16MB, causing notEnoughToRepeat when the data references bytes beyond this undersized window.
Proposed Fix
Change 1..<4 to 1..<5:
Verification
Test archive info from 7z t:
Method = LZMA:24
Solid = +
Physical Size = 86250112
The archive is valid and decompresses correctly with the official 7-Zip implementation.
Related
This may be related to issue #40, which was fixed in 4.8.5 for LZMA2. However, this bug is in the LZMA (not LZMA2) code path in 7zFolder.swift.