Skip to content

Conversation

@analytical-engines
Copy link

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

  • SWCompression version: 4.8.6
  • Platform: macOS 15.2 (Darwin 25.1.0)
  • Swift version: 5.x

Steps to Reproduce

  1. Create or obtain a 7z archive compressed with LZMA and dictionary size 16MB or larger (e.g., LZMA:24 = 2^24 = 16MB)
  2. Attempt to decompress using SevenZipContainer.open(container:)
  3. Decompression fails with LZMAError.notEnoughToRepeat

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:

  var dictionarySize = 0
  for i in 1..<4 {
      dictionarySize |= properties[i].toInt() << (8 * (i - 1))
  }

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:

  var dictionarySize = 0
  for i in 1..<5 {
      dictionarySize |= properties[i].toInt() << (8 * (i - 1))
  }

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.

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`
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