Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PNG iCCP chunk profile compression type verification seems wrong #7817

Closed
nathaniel-daniel opened this issue Feb 20, 2024 · 1 comment · Fixed by #7823
Closed

PNG iCCP chunk profile compression type verification seems wrong #7817

nathaniel-daniel opened this issue Feb 20, 2024 · 1 comment · Fixed by #7823

Comments

@nathaniel-daniel
Copy link

nathaniel-daniel commented Feb 20, 2024

What did you do?

Hello, I've been looking around at some PNG decoders and I think I've found a small bug in your iCCP chunk handling.

What did you expect to happen?

I would expect the library to read the iCCP chunk compression version byte correctly.

What actually happened?

This library incorrectly assumes that the NUL terminator is the compression byte. This does not cause issues in practice, since the compression byte should currently always be 0, but I thought I'd report this anyways.

What are your OS, Python and Pillow versions?

  • OS: Windows
  • Python: Python 3.11.8-1 (MSYS2)
  • Pillow: 10.2.0-1 (MSYS2)
from PIL import Image, ImageFile
import logging

logging.basicConfig(level=logging.DEBUG)

path = 'ArcTriomphe-iCCP-red-green-swap-mod.png'

with Image.open(path) as img:
    icc = img.info.get('icc_profile')
    print(icc)
    print(img)

Here are my 2 test files:
ArcTriomphe-iCCP-red-green-swap
ArcTriomphe-iCCP-red-green-swap-mod

The first one is a normal image with an embedded icc profile. The second is the same image, modified in a hex editor to change the compression version field from 0 to 1.

Here is the output from the first image:

DEBUG:PIL.PngImagePlugin:STREAM b'IHDR' 16 13
DEBUG:PIL.PngImagePlugin:STREAM b'iCCP' 41 460
DEBUG:PIL.PngImagePlugin:iCCP profile name b'Swapped red & green channel'
DEBUG:PIL.PngImagePlugin:Compression method 0
DEBUG:PIL.PngImagePlugin:STREAM b'PLTE' 513 759
DEBUG:PIL.PngImagePlugin:STREAM b'IDAT' 1284 3618
b'\x00\x00\x02\x84lcms\x02@\x00\x00mntrRGB XYZ \x07\xd5\x00\x08\x00\r\x00\x16\x00!\x00,acspSUNW\x00\x00\x00\x00none\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-Greg^\xdf\x16\x9a"\xbb\xfd\xab\xb6@n\xf998\rz\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ndesc\x00\x00\x00\xfc\x00\x00\x00\x84cprt\x00\x00\x01\x80\x00\x00\x00\x90wtpt\x00\x00\x02\x10\x00\x00\x00\x14bkpt\x00\x00\x02$\x00\x00\x00\x14rXYZ\x00\x00\x028\x00\x00\x00\x14gXYZ\x00\x00\x02L\x00\x00\x00\x14bXYZ\x00\x00\x02`\x00\x00\x00\x14rTRC\x00\x00\x02t\x00\x00\x00\x0egTRC\x00\x00\x02t\x00\x00\x00\x0ebTRC\x00\x00\x02t\x00\x00\x00\x0edesc\x00\x00\x00\x00\x00\x00\x00\'"sGRB": red and green channels swapped\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0067 bytes of wasted space, courtesy of Apple Computer, dum de dum.\x00\x00text\x00\x00\x00\x00Copyright 2005 Greg Roelofs. Licensed under Creative Commons Attribution-NonCommercial, http://creativecommons.org/licenses/by-nc/2.5/ \x00XYZ \x00\x00\x00\x00\x00\x00\xf3Q\x00\x01\x00\x00\x00\x01\x16\xccXYZ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00XYZ \x00\x00\x00\x00\x00\x00b\x98\x00\x00\xb7\x86\x00\x00\x18\xdaXYZ \x00\x00\x00\x00\x00\x00o\xa1\x00\x008\xf5\x00\x00\x03\x90XYZ \x00\x00\x00\x00\x00\x00$\xa0\x00\x00\x0f\x84\x00\x00\xb6\xc9curv\x00\x00\x00\x00\x00\x00\x00\x01\x023\x00\x00'
<PIL.PngImagePlugin.PngImageFile image mode=P size=64x64 at 0x26C30640E10>

Here is the output from the second image:

DEBUG:PIL.PngImagePlugin:STREAM b'IHDR' 16 13
DEBUG:PIL.PngImagePlugin:STREAM b'iCCP' 41 460
DEBUG:PIL.PngImagePlugin:iCCP profile name b'Swapped red & green channel'
DEBUG:PIL.PngImagePlugin:Compression method 0
DEBUG:PIL.Image:Importing BlpImagePlugin
DEBUG:PIL.Image:Importing BmpImagePlugin
DEBUG:PIL.Image:Importing BufrStubImagePlugin
DEBUG:PIL.Image:Importing CurImagePlugin
DEBUG:PIL.Image:Importing DcxImagePlugin
DEBUG:PIL.Image:Importing DdsImagePlugin
DEBUG:PIL.Image:Importing EpsImagePlugin
DEBUG:PIL.Image:Importing FitsImagePlugin
DEBUG:PIL.Image:Importing FliImagePlugin
DEBUG:PIL.Image:Importing FpxImagePlugin
DEBUG:PIL.Image:Image: failed to import FpxImagePlugin: No module named 'olefile'
DEBUG:PIL.Image:Importing FtexImagePlugin
DEBUG:PIL.Image:Importing GbrImagePlugin
DEBUG:PIL.Image:Importing GifImagePlugin
DEBUG:PIL.Image:Importing GribStubImagePlugin
DEBUG:PIL.Image:Importing Hdf5StubImagePlugin
DEBUG:PIL.Image:Importing IcnsImagePlugin
DEBUG:PIL.Image:Importing IcoImagePlugin
DEBUG:PIL.Image:Importing ImImagePlugin
DEBUG:PIL.Image:Importing ImtImagePlugin
DEBUG:PIL.Image:Importing IptcImagePlugin
DEBUG:PIL.Image:Importing JpegImagePlugin
DEBUG:PIL.Image:Importing Jpeg2KImagePlugin
DEBUG:PIL.Image:Importing McIdasImagePlugin
DEBUG:PIL.Image:Importing MicImagePlugin
DEBUG:PIL.Image:Image: failed to import MicImagePlugin: No module named 'olefile'
DEBUG:PIL.Image:Importing MpegImagePlugin
DEBUG:PIL.Image:Importing MpoImagePlugin
DEBUG:PIL.Image:Importing MspImagePlugin
DEBUG:PIL.Image:Importing PalmImagePlugin
DEBUG:PIL.Image:Importing PcdImagePlugin
DEBUG:PIL.Image:Importing PcxImagePlugin
DEBUG:PIL.Image:Importing PdfImagePlugin
DEBUG:PIL.Image:Importing PixarImagePlugin
DEBUG:PIL.Image:Importing PngImagePlugin
DEBUG:PIL.Image:Importing PpmImagePlugin
DEBUG:PIL.Image:Importing PsdImagePlugin
DEBUG:PIL.Image:Importing QoiImagePlugin
DEBUG:PIL.Image:Importing SgiImagePlugin
DEBUG:PIL.Image:Importing SpiderImagePlugin
DEBUG:PIL.Image:Importing SunImagePlugin
DEBUG:PIL.Image:Importing TgaImagePlugin
DEBUG:PIL.Image:Importing TiffImagePlugin
DEBUG:PIL.Image:Importing WebPImagePlugin
DEBUG:PIL.Image:Importing WmfImagePlugin
DEBUG:PIL.Image:Importing XbmImagePlugin
DEBUG:PIL.Image:Importing XpmImagePlugin
DEBUG:PIL.Image:Importing XVThumbImagePlugin
<traceback omitted>
PIL.UnidentifiedImageError: cannot identify image file 'ArcTriomphe-iCCP-red-green-swap-mod.png'

As can be seen, PIL thinks the compression byte never changes. The issue is here, where there is an off-by-one error. s[i] should be s[i + 1] for the compression byte.

@radarhere radarhere changed the title PNG iCCP Chunk Profile Compression Type Verification Seems Wrong PNG iCCP chunk profile compression type verification seems wrong Feb 20, 2024
@radarhere
Copy link
Member

I've created #7823 to resolve this.

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 a pull request may close this issue.

2 participants