Raise a truncated chunk error for a short gAMA chunk - #9880
Open
VenishPaneliya wants to merge 1 commit into
Open
Raise a truncated chunk error for a short gAMA chunk#9880VenishPaneliya wants to merge 1 commit into
VenishPaneliya wants to merge 1 commit into
Conversation
gAMA carries a single 4-byte gamma value, but chunk_gAMA read it with
i32() without first checking the chunk length. A PNG whose gAMA chunk is
shorter than 4 bytes raised struct.error, which ImageFile turns into a
SyntaxError, so Image.open() reported "cannot identify image file" for a
file that is otherwise a perfectly readable PNG.
LOAD_TRUNCATED_IMAGES could not rescue it either: sRGB, pHYs, IHDR, acTL,
fcTL and fdAT all return the short chunk when it is set and otherwise
raise ValueError("Truncated <cid> chunk"), but gAMA failed before
reaching that logic. Guard it the same way and add gAMA to the existing
test_truncated_chunks parametrisation, which already covers the others.
radarhere
approved these changes
Aug 20, 2026
Member
|
Hi. Thanks for this. Curious question - did you actually find an image in the wild where this was truncated, or is this a theoretical concern? Regarding |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
chunk_gAMAreads the 4-byte gamma value withi32(s)without first checking the chunk length. A PNG whosegAMAchunk is shorter than 4 bytes raisesstruct.error, whichImageFile.__init__converts toSyntaxError, whichImage.open()treats as "this isn't a PNG" — so the user seesUnidentifiedImageError: cannot identify image filefor a file that is otherwise a perfectly readable PNG.LOAD_TRUNCATED_IMAGEScan't rescue it either, because the failure happens before any truncation handling runs.The sibling chunk handlers already do this correctly.
IHDR,sRGB,pHYs,acTL,fcTLandfdATall check the length first and either return the short chunk whenLOAD_TRUNCATED_IMAGESis set, or raiseValueError("Truncated <cid> chunk").gAMAis the one fixed-size chunk missing that guard — and it's also the one missing from the existingtest_truncated_chunksparametrisation.Reproduction
Before:
(underlying cause:
struct.error: unpack_from requires a buffer of at least 4 bytes)After, matching
sRGBexactly:LOAD_TRUNCATED_IMAGES = False→ValueError: Truncated gAMA chunkLOAD_TRUNCATED_IMAGES = True→ loads fineChanges
and
b"gAMA"added to the existingtest_truncated_chunksparametrisation, which already covers the other guarded chunks.Tests
Tests/test_file_png.py::TestFilePng::test_truncated_chunks[gAMA]fails on currentmainwithstruct.errorand passes with the guard. FullTests/test_file_png.py: 65 passed, 1 skipped (the skip is Unix-only).ruffandblackclean on both changed files.One question
chunk_cHRMhas the same crash —struct.unpack(f">{len(s) // 4}I", s)raisesstruct.errorwhen the length isn't a multiple of 4. I left it out of this PR because the right guard there is a judgement call: strict (length < 32, per spec) would reject short-but-parseable chromaticity chunks that currently decode into a partial tuple. Happy to add whichever you prefer, here or separately.