Skip to content

lzma: unbounded dictionary-size allocation is a memory DoS (zipfile, tarfile, lzma.decompress) #155649

Description

@DeseretSaint

Bug: LZMA decompression accepts an attacker-controlled dictionary size with no bound, and liblzma allocates the full dictionary up front when a decompressor is created. A few bytes of input can therefore force a multi-gigabyte allocation (memory denial of service).

Attack surfaces (both reported by OSS-Fuzz, both public):

  • zipfile with an LZMA-compressed member: the 5-byte LZMA properties header in the member data declares the dictionary. A 1088-byte zip whose member declares a ~2 GiB dictionary OOMs the process. https://issues.oss-fuzz.com/issues/495472861
  • tarfile's compression-detection loop: a 13-byte input whose first byte is a valid LZMA-alone properties byte (0x66) and whose remaining bytes encode a ~4 GiB dictionary is tried as LZMA; liblzma allocates 4 GiB before failing. https://issues.oss-fuzz.com/issues/482161128

Also reachable directly: lzma.decompress() / LZMADecompressor(format=FORMAT_AUTO) on untrusted bytes, and LZMADecompressor(FORMAT_RAW, filters=[{"dict_size": ...}]).

Root cause: two gaps:

  1. parse_filter_spec_lzma() accepts any dict_size (up to UINT32_MAX) for raw LZMA1/LZMA2 filter chains; liblzma allocates that dictionary at decompressor creation.
  2. LZMADecompressor defaults memlimit to UINT64_MAX, so the FORMAT_ALONE/FORMAT_AUTO paths (where the header is parsed inside liblzma) are also unbounded.

Proposed fix (PR to follow):

  • Reject dict_size > LZMA_DICT_SIZE_MAX (1.5 GiB, liblzma's own maximum) in parse_filter_spec_lzma() with LZMAError.
  • Default the decompressor memlimit to LZMA_DICT_SIZE_MAX instead of UINT64_MAX (callers may still pass an explicit memlimit).

No legitimate streams are affected: liblzma presets cap at 64 MiB dictionaries, and 1.5 GiB is liblzma's own maximum supported dictionary size.

Reported by OSS-Fuzz (ClusterFuzz). Reproducers attached to the issues above.

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions