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()
openSUSE Build Service is sponsored by