GeezerVison is showing github.com — gh-132983: Don't allow trailer data in ZstdFile by Rogdham · Pull Request #133736 · python/cpython
Conversation
Rogdham
commented
May 9, 2025
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
We previously made sure that an exception is raised when decompressing trailer data with decompress:
>>> from compression.zstd import compress, decompress
>>> invalid = compress(b'xxx') + b'yyy'
>>> decompress(invalid)
Traceback (most recent call last):
File "<python-input-2>", line 1, in <module>
decompress(invalid)
~~~~~~~~~~^^^^^^^^^
File "/redacted/Lib/compression/zstd/__init__.py", line 157, in decompress
results.append(decomp.decompress(data))
~~~~~~~~~~~~~~~~~^^^^^^
_zstd.ZstdError: Unable to decompress zstd data: Unknown frame descriptor
Indeed, the Zstandard specification says “Zstandard compressed data is made of one or more frames”, and it does not say that random data can be added at the end.
However, this is not the case in ZstdFile / zstd.open:
>>> from compression.zstd import ZstdFile
>>> from io import BytesIO
>>> ZstdFile(BytesIO(invalid)).read()
b'xxx'
After this PR, the last call becomes:
>>> ZstdFile(BytesIO(invalid)).read()
Traceback (most recent call last):
File "<python-input-5>", line 1, in <module>
ZstdFile(BytesIO(invalid)).read()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/redacted/Lib/compression/zstd/_zstdfile.py", line 176, in read
return self._buffer.read(size)
~~~~~~~~~~~~~~~~~^^^^^^
File "/redacted/Lib/compression/_common/_streams.py", line 118, in readall
while data := self.read(sys.maxsize):
~~~~~~~~~^^^^^^^^^^^^^
File "/redacted/Lib/compression/_common/_streams.py", line 91, in read
data = self._decompressor.decompress(rawblock, size)
_zstd.ZstdError: Unable to decompress zstd data: Unknown frame descriptor
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
The current behavior matches LZMA. I think unlike decompress which is handed what is necessarily a zstd stream of one or more frames, with ZstdFile, a user may be parsing a format which has additional information after a zstd stream.
>>> from lzma import LZMAFile, compress
>>> from io import BytesIO
>>> invalid = compress(b'foo') + b'bar'
>>> LZMAFile(BytesIO(invalid)).read()
b'foo'
>>>
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
You are right this is the case for LZMAFile with format FORMAT_AUTO (which is the default) and also for BZ2File.
However, LZMAFile with format FORMAT_XZ as well as GzipFile raise an exception in that case.
>>> from lzma import LZMAFile, compress, FORMAT_XZ
>>> from io import BytesIO
>>> invalid = compress(b'foo') + b'bar'
>>> LZMAFile(BytesIO(invalid), format=FORMAT_XZ).read()
Traceback (most recent call last):
File "<python-input-3>", line 1, in <module>
LZMAFile(BytesIO(invalid), format=FORMAT_XZ).read()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/redacted/lzma.py", line 208, in read
return self._buffer.read(size)
~~~~~~~~~~~~~~~~~^^^^^^
File "/redacted/_compression.py", line 118, in readall
while data := self.read(sys.maxsize):
~~~~~~~~~^^^^^^^^^^^^^
File "/redacted/_compression.py", line 99, in read
raise EOFError("Compressed file ended before the "
"end-of-stream marker was reached")
EOFError: Compressed file ended before the end-of-stream marker was reached
|
emmatyping reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay this looks good then!
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Rogdham
commented
May 9, 2025
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
In addition, consider decompress(compress(b"xxx") + b"yyy"):
- returns
b"xxx" on: lzma (format FORMAT_AUTO), bz2
- raises an exception on:
lzma (format FORMAT_XZ), gzip
Since for zstd we raise an exception on that, I would say to do the same for ZstdFile to be consistent.
|
emmatyping reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Thanks @Rogdham for the PR, and @AA-Turner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14.
🐍🍒⛏🤖
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
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.
|