Skip to content

Fix crash in StuffItX parser when block size overflows#189

Open
alek-prykhodko wants to merge 3 commits into
masterfrom
fix/stuffitx-blocksize-overflow
Open

Fix crash in StuffItX parser when block size overflows#189
alek-prykhodko wants to merge 3 commits into
masterfrom
fix/stuffitx-blocksize-overflow

Conversation

@alek-prykhodko
Copy link
Copy Markdown
Member

@alek-prykhodko alek-prykhodko commented Jun 1, 2026

Summary

When extracting StuffItX archives, the decompression block size is read from the compressed stream as a uint64_t via CSInputNextSitxP2, then immediately cast to unsigned int. In malformed archives this value can exceed INT_MAX, causing the cast to overflow and produce a wrong blocksize. A second overflow occurs when computing the allocation size: blocksize*6 is evaluated in unsigned int arithmetic before being passed to malloc(), and wraps around to a small value. malloc succeeds with that undersized buffer, but sorted and table are computed using the original blocksize as an offset — placing them far outside the allocation and turning any access through them into a crash:

  Exception Type:  EXC_BAD_ACCESS (KERN_INVALID_ADDRESS)
  Exception Codes: Exception 1, Code 1, Subcode 16100407620

  Thread Crashed:
        0  XADMaster    -[XADStuffItXIronHandle decodeBlockWithLength:]
        1  XADMaster    -[XADStuffItXIronHandle produceBlockAtOffset:]
        2  XADMaster    -[XADBlockStreamHandle _readNextBlock]
        3  XADMaster    -[XADBlockStreamHandle streamAtMost:toBuffer:]
        4  XADMaster    -[XADStreamHandle readAtMost:toBuffer:]
        5  XADMaster    -[XADUnarchiver runExtractorWithDictionary:outputTarget:selector:argument:]

Key Changes

  • Validate the raw block size against UINT_MAX before casting to unsigned int.
  • Compute the allocation size as size_t allocsize = (size_t)blocksize * 6 so the multiplication happens in 64-bit arithmetic and cannot overflow.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a crash in the StuffItX “Iron” decompressor caused by integer truncation/overflow when reading a malformed block size from the compressed stream.

Changes:

  • Reads the block size as uint64_t and validates it before narrowing to unsigned int.
  • Computes the allocation size using size_t and uses that value for malloc().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread XADStuffItXIronHandle.m
Comment thread XADStuffItXIronHandle.m Outdated
@alek-prykhodko alek-prykhodko force-pushed the fix/stuffitx-blocksize-overflow branch from d487746 to b76757c Compare June 1, 2026 15:02
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

XADStuffItXIronHandle.m:115

  • table is derived from block + 2*blocksize and cast to uint32_t *. If blocksize is not 2-byte aligned, this can produce a misaligned uint32_t * (undefined behavior and potential crash on alignment-sensitive architectures). Consider aligning the table offset to alignof(uint32_t) and adjusting the allocation size accordingly.
		block=malloc(allocsize);
		if(!block) [XADException raiseOutOfMemoryException];
		sorted=block+blocksize;
		table=(uint32_t *)(block+2*blocksize);
		currsize=blocksize;

Comment thread XADStuffItXIronHandle.m
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