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

Ability to skip crc checks for ancillary chunks #1991

Merged
merged 3 commits into from
Jun 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions PIL/PngImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ def call(self, cid, pos, length):
def crc(self, cid, data):
"Read and verify checksum"

# Skip CRC checks for ancillary chunks if allowed to load truncated images
# 5th byte of first char is 1 [specs, section 5.4]
if ImageFile.LOAD_TRUNCATED_IMAGES and (i8(cid[0]) >> 5 & 1):
Copy link
Member

Choose a reason for hiding this comment

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

I'd prefer to ignore the error after it occurs. Of course, it is meaningless to do the check, if we are going to accept the result in any case. But in the future, we can add some warnings or other decoder info.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm, why bother doing this now, if in both cases code has to be changed to throw a warning?
But anyway, I can keep crc check if you'd like. Would you like to ignore checksum mismatch or incomplete checksum as well?

self.crc_skip(cid, data)
return

try:
crc1 = Image.core.crc32(data, Image.core.crc32(cid))
crc2 = i16(self.fp.read(2)), i16(self.fp.read(2))
Expand Down
28 changes: 28 additions & 0 deletions Tests/test_file_png.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from io import BytesIO

from PIL import Image
from PIL import ImageFile
from PIL import PngImagePlugin
import zlib

Expand Down Expand Up @@ -319,6 +320,33 @@ def test_verify_struct_error(self):
self.assertTrue(im.fp is not None)
self.assertRaises((IOError, SyntaxError), im.verify)

def test_verify_ignores_crc_error(self):
# check ignores crc errors in ancillary chunks

chunk_data = chunk(b'tEXt', b'spam')
broken_crc_chunk_data = chunk_data[:-1] + b'q' # break CRC

image_data = HEAD + broken_crc_chunk_data + TAIL
self.assertRaises(SyntaxError, PngImagePlugin.PngImageFile, BytesIO(image_data))

ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
im = load(image_data)
self.assertTrue(im is not None)
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False

def test_verify_not_ignores_crc_error_in_required_chunk(self):
# check does not ignore crc errors in required chunks

image_data = MAGIC + IHDR[:-1] + b'q' + TAIL

ImageFile.LOAD_TRUNCATED_IMAGES = True
try:
self.assertRaises(SyntaxError, PngImagePlugin.PngImageFile, BytesIO(image_data))
finally:
ImageFile.LOAD_TRUNCATED_IMAGES = False


def test_roundtrip_dpi(self):
# Check dpi roundtripping
Expand Down