Skip to content

gh-148286: Fix UB in ZstdDecompressor.unused_data when a frame is decompressed in one call#153258

Open
StanFromIreland wants to merge 1 commit into
python:mainfrom
StanFromIreland:zstd-unused-data
Open

gh-148286: Fix UB in ZstdDecompressor.unused_data when a frame is decompressed in one call#153258
StanFromIreland wants to merge 1 commit into
python:mainfrom
StanFromIreland:zstd-unused-data

Conversation

@StanFromIreland

@StanFromIreland StanFromIreland commented Jul 7, 2026

Copy link
Copy Markdown
Member

To reproduce, run test_zstd.CompressorTestCase.test_compress_flushblock or under UBSan:

>>> from compression.zstd import ZstdDecompressor, compress
>>> d = ZstdDecompressor()
>>> d.decompress(compress(b'Hi Emma!'))
b'Hi Emma!'
>>> d.unused_data
Modules/_zstd/decompressor.c:598:56: runtime error: applying non-zero offset 18446744073709551615 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Modules/_zstd/decompressor.c:598:56 
b''
>>> 

ZstdDecompressor.unused_data computes self->input_buffer + self->in_begin without checking that input_buffer was ever allocated, so when a frame is fully consumed in a single decompress() call it leaves input_buffer NULL (and in_begin/in_end at their initial state). Reading .unused_data evaluates NULL + ..., which is UB. Although the resulting length of in_end - in_begin == 0 means it accidentally returns the correct b''.

The other unused_data implementations are not affected due to their design.

Also, CC @Rogdham

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant