Fixed #24544 -- Fixed get_image_dimensions() on image buffers that Pillow fails to parse.

Thanks Steve Kossouho for the report and original patch.
This commit is contained in:
steve 2015-03-27 20:54:14 +01:00 committed by Tim Graham
parent 800240cb1d
commit 2fc19b9238
2 changed files with 25 additions and 2 deletions

View File

@ -3,6 +3,7 @@ Utility functions for handling images.
Requires Pillow as you might imagine. Requires Pillow as you might imagine.
""" """
import struct
import zlib import zlib
from django.core.files import File from django.core.files import File
@ -63,6 +64,11 @@ def get_image_dimensions(file_or_path, close=False):
pass pass
else: else:
raise raise
except struct.error as e:
# Ignore PIL failing on a too short buffer when reads return
# less bytes than expected. Skip and feed more data to the
# parser (ticket #24544).
pass
if p.image: if p.image:
return p.image.size return p.image.size
chunk_size *= 2 chunk_size *= 2

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
import gzip import gzip
import os import os
import struct
import tempfile import tempfile
import unittest import unittest
import zlib import zlib
@ -13,6 +14,7 @@ from django.core.files.base import ContentFile
from django.core.files.move import file_move_safe from django.core.files.move import file_move_safe
from django.core.files.temp import NamedTemporaryFile from django.core.files.temp import NamedTemporaryFile
from django.core.files.uploadedfile import SimpleUploadedFile, UploadedFile from django.core.files.uploadedfile import SimpleUploadedFile, UploadedFile
from django.test import mock
from django.utils import six from django.utils import six
from django.utils._os import upath from django.utils._os import upath
@ -239,8 +241,9 @@ class InconsistentGetImageDimensionsBug(unittest.TestCase):
self.assertEqual(size, Image.open(fh).size) self.assertEqual(size, Image.open(fh).size)
class GetImageDimensionsOnInvalidImages(unittest.TestCase): @unittest.skipUnless(Image, "Pillow not installed")
@unittest.skipUnless(Image, "Pillow not installed") class GetImageDimensionsTests(unittest.TestCase):
def test_invalid_image(self): def test_invalid_image(self):
""" """
get_image_dimensions() should return (None, None) for the dimensions of get_image_dimensions() should return (None, None) for the dimensions of
@ -254,6 +257,20 @@ class GetImageDimensionsOnInvalidImages(unittest.TestCase):
size = images.get_image_dimensions(fh) size = images.get_image_dimensions(fh)
self.assertEqual(size, (None, None)) self.assertEqual(size, (None, None))
def test_valid_image(self):
"""
get_image_dimensions() should catch struct.error while feeding the PIL
Image parser (#24544).
Emulates the Parser feed error. Since the error is raised on every feed
attempt, the resulting image size should be invalid: (None, None).
"""
img_path = os.path.join(os.path.dirname(upath(__file__)), "test.png")
with mock.patch('PIL.ImageFile.Parser.feed', side_effect=struct.error):
with open(img_path, 'rb') as fh:
size = images.get_image_dimensions(fh)
self.assertEqual(size, (None, None))
class FileMoveSafeTests(unittest.TestCase): class FileMoveSafeTests(unittest.TestCase):
def test_file_move_overwrite(self): def test_file_move_overwrite(self):