File 0010-Crop-decompression.patch of Package python-Pillow
From c70977aad7196104c975fd89fe0e3f621fa1a84b Mon Sep 17 00:00:00 2001
From: wiredfool <eric-github@soroos.net>
Date: Fri, 17 Feb 2017 07:07:14 -0800
Subject: [PATCH 1/2] added decompression bomb check to crop
---
PIL/Image.py | 18 +++++++++++++++++-
Tests/test_decompression_bomb.py | 23 +++++++++++++++++++----
2 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/PIL/Image.py b/PIL/Image.py
index c22ab3955d..9910d21623 100644
--- a/PIL/Image.py
+++ b/PIL/Image.py
@@ -1021,6 +1021,20 @@ def crop(self, box=None):
if box is None:
return self.copy()
+ return self._new(self._crop(self.im, box))
+
+ def _crop(self, im, box):
+ """
+ Returns a rectangular region from the core image object im.
+
+ This is equivalent to calling im.crop((x0, y0, x1, y1)), but
+ includes additional sanity checks.
+
+ :param im: a core image object
+ :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
+ :returns: A core image object.
+ """
+
x0, y0, x1, y1 = map(int, map(round, box))
if x1 < x0:
@@ -1028,8 +1042,10 @@ def crop(self, box=None):
if y1 < y0:
y1 = y0
- return self._new(self.im.crop(( x0, y0, x1, y1)))
+ _decompression_bomb_check((x1, y1))
+ return im.crop((x0, y0, x1, y1))
+
def draft(self, mode, size):
"""
Configures the image file loader so it returns a version of the
diff --git a/Tests/test_decompression_bomb.py b/Tests/test_decompression_bomb.py
index 675005d3f0..5598fd9c87 100644
--- a/Tests/test_decompression_bomb.py
+++ b/Tests/test_decompression_bomb.py
@@ -1,4 +1,4 @@
-from helper import unittest, PillowTestCase
+from helper import unittest, PillowTestCase, hopper
from PIL import Image
@@ -35,9 +35,24 @@ def test_warning(self):
self.assertEqual(Image.MAX_IMAGE_PIXELS, 10)
# Act / Assert
- self.assert_warning(
- Image.DecompressionBombWarning,
- lambda: Image.open(TEST_FILE))
+ self.assert_warning(Image.DecompressionBombWarning,
+ lambda: Image.open(TEST_FILE))
+
+class TestDecompressionCrop(PillowTestCase):
+
+ def setUp(self):
+ self.src = hopper()
+ Image.MAX_IMAGE_PIXELS = self.src.size[1] * self.src.size[0]
+
+ def tearDown(self):
+ Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
+
+ def testEnlargeCrop(self):
+ # Crops can extend the extents, therefore we should have the
+ # same decompression bomb warnings on them.
+ box = (0, 0, self.src.size[0] * 2, self.src.size[1] * 2)
+ self.assert_warning(Image.DecompressionBombWarning,
+ lambda: self.src.crop(box))
if __name__ == '__main__':
unittest.main()
From 228c5bb292bb72b87bc4d5fc6826a94b47f2edbd Mon Sep 17 00:00:00 2001
From: wiredfool <eric-github@soroos.net>
Date: Fri, 17 Feb 2017 07:18:18 -0800
Subject: [PATCH 2/2] using the decompression bomb _crop filter
---
PIL/GifImagePlugin.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/PIL/GifImagePlugin.py b/PIL/GifImagePlugin.py
index b20fdd452d..75158809d3 100644
--- a/PIL/GifImagePlugin.py
+++ b/PIL/GifImagePlugin.py
@@ -214,7 +214,7 @@ def _seek(self, frame):
# only dispose the extent in this frame
if self.dispose:
- self.dispose = self.dispose.crop(self.dispose_extent)
+ self.dispose = self._crop(self.dispose, self.dispose_extent)
except (AttributeError, KeyError):
pass
@@ -237,7 +237,7 @@ def load_end(self):
if self._prev_im and self.disposal_method == 1:
# we do this by pasting the updated area onto the previous
# frame which we then use as the current image content
- updated = self.im.crop(self.dispose_extent)
+ updated = self._crop(self.im, self.dispose_extent)
self._prev_im.paste(updated, self.dispose_extent,
updated.convert('RGBA'))
self.im = self._prev_im