File 0009-Make-Image.crop-an-immediate-operation.patch of Package python-Pillow
From 95b50bf611b53bdff18fb00fd2d272cedf988232 Mon Sep 17 00:00:00 2001
From: Eric Soroos <eric-github@soroos.net>
Date: Thu, 29 Sep 2016 13:28:24 -0700
Subject: [PATCH] Make Image.crop an immediate operation, not lazy. Fixes #1077
---
PIL/Image.py | 53 ++++++++--------------------------------
Tests/test_image_crop.py | 18 ++++++++++++++
2 files changed, 28 insertions(+), 43 deletions(-)
diff --git a/PIL/Image.py b/PIL/Image.py
index 2f68e88b58..13ab247543 100644
--- a/PIL/Image.py
+++ b/PIL/Image.py
@@ -1010,10 +1010,7 @@ def crop(self, box=None):
4-tuple defining the left, upper, right, and lower pixel
coordinate.
- This is a lazy operation. Changes to the source image may or
- may not be reflected in the cropped image. To break the
- connection, call the :py:meth:`~PIL.Image.Image.load` method on
- the cropped copy.
+ Note: Prior to Pillow 3.4.0, this was a lazy operation.
:param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
:rtype: :py:class:`~PIL.Image.Image`
@@ -1024,8 +1021,14 @@ def crop(self, box=None):
if box is None:
return self.copy()
- # lazy operation
- return _ImageCrop(self, box)
+ x0, y0, x1, y1 = map(int, map(round, box))
+
+ if x1 < x0:
+ x1 = x0
+ if y1 < y0:
+ y1 = y0
+
+ return self._new(self.im.crop(( x0, y0, x1, y1)))
def draft(self, mode, size):
"""
@@ -1935,42 +1939,6 @@ def effect_spread(self, distance):
im = self.im.effect_spread(distance)
return self._new(im)
-
-# --------------------------------------------------------------------
-# Lazy operations
-
-class _ImageCrop(Image):
-
- def __init__(self, im, box):
-
- Image.__init__(self)
-
- x0, y0, x1, y1 = box
- if x1 < x0:
- x1 = x0
- if y1 < y0:
- y1 = y0
-
- self.mode = im.mode
- self.size = x1-x0, y1-y0
-
- self.__crop = x0, y0, x1, y1
-
- self.im = im.im
-
- def load(self):
-
- # lazy evaluation!
- if self.__crop:
- self.im = self.im.crop(self.__crop)
- self.__crop = None
-
- if self.im:
- return self.im.pixel_access(self.readonly)
-
- # FIXME: future versions should optimize crop/paste
- # sequences!
-
# --------------------------------------------------------------------
# Abstract handlers.
diff --git a/Tests/test_image_crop.py b/Tests/test_image_crop.py
index 2a99a6213a..c12e29be41 100644
--- a/Tests/test_image_crop.py
+++ b/Tests/test_image_crop.py
@@ -52,6 +52,24 @@ def test_negative_crop(self):
self.assertEqual(len(im.getdata()), 0)
self.assertRaises(IndexError, lambda: im.getdata()[0])
+ def test_crop_crash(self):
+ #Image.crop crashes prepatch with an access violation
+ #apparently a use after free on windows, see
+ #https://github.com/python-pillow/Pillow/issues/1077
+
+ test_img = 'Tests/images/bmp/g/pal8-0.bmp'
+ extents = (1,1,10,10)
+ #works prepatch
+ img = Image.open(test_img)
+ img2 = img.crop(extents)
+ img2.load()
+
+ # fail prepatch
+ img = Image.open(test_img)
+ img = img.crop(extents)
+ img.load()
+
+
if __name__ == '__main__':
unittest.main()