From c6ec3be0d6183d04c5d3d8e2057e7a6a74edf602 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 15 Mar 2016 19:56:40 +0000 Subject: [PATCH 1/3] Fix for integer overflow in path.c --- Tests/test_imagepath.py | 30 +++++++++++++++++++++++++++++- path.c | 4 ++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py index cd221b5ca..f63d3fcf1 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -3,7 +3,7 @@ from helper import unittest, PillowTestCase from PIL import ImagePath import array - +import struct class TestImagePath(PillowTestCase): @@ -62,6 +62,34 @@ class TestImagePath(PillowTestCase): self.assertEqual(list(p), [(0.0, 1.0)]) + def test_overflow_segfault(self): + try: + # post patch, this fails with a memory error + x = evil() + + # This fails due to the invalid malloc above, + # and segfaults + for i in xrange(200000): + x[i] = "0"*16 + + except MemoryError as msg: + self.assertTrue(msg) + except: + self.asserTrue(False, "Should have received a memory error") + + +class evil: + def __init__(self): + self.corrupt = ImagePath.Path(0x4000000000000000) + + def __getitem__(self, i): + x = self.corrupt[i] + return struct.pack("dd", x[0], x[1]) + + def __setitem__(self, i, x): + self.corrupt[i] = struct.unpack("dd", x) + + if __name__ == '__main__': unittest.main() diff --git a/path.c b/path.c index db4a68e24..dd0ca8b4e 100644 --- a/path.c +++ b/path.c @@ -57,6 +57,10 @@ alloc_array(Py_ssize_t count) PyErr_NoMemory(); return NULL; } + if (count > (SIZE_MAX / (2 * sizeof(double))) - 1 ) { + PyErr_NoMemory(); + return NULL; + } xy = malloc(2 * count * sizeof(double) + 1); if (!xy) PyErr_NoMemory(); From f65fcf7274aacf161d16f1f0c628f1620610732d Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 16 Mar 2016 10:03:38 +0000 Subject: [PATCH 2/3] Fixing the tests on py 3.x --- Tests/test_imagepath.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py index f63d3fcf1..8077f1a2a 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -1,6 +1,6 @@ from helper import unittest, PillowTestCase -from PIL import ImagePath +from PIL import ImagePath, Image import array import struct @@ -69,18 +69,21 @@ class TestImagePath(PillowTestCase): # This fails due to the invalid malloc above, # and segfaults - for i in xrange(200000): - x[i] = "0"*16 + for i in range(200000): + if str is bytes: + x[i] = "0"*16 + else: + x[i] = b'0'*16 except MemoryError as msg: self.assertTrue(msg) except: - self.asserTrue(False, "Should have received a memory error") + self.assertTrue(False, "Should have received a memory error") class evil: def __init__(self): - self.corrupt = ImagePath.Path(0x4000000000000000) + self.corrupt = Image.core.path(0x4000000000000000) def __getitem__(self, i): x = self.corrupt[i] From 0c4131bf67ab0a660db8773a0727dd96c997313f Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 26 Mar 2016 15:01:26 -0700 Subject: [PATCH 3/3] Fixing tests on windows/32bit --- Tests/test_imagepath.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py index 8077f1a2a..0354b0fd9 100644 --- a/Tests/test_imagepath.py +++ b/Tests/test_imagepath.py @@ -74,7 +74,10 @@ class TestImagePath(PillowTestCase): x[i] = "0"*16 else: x[i] = b'0'*16 - + except TypeError as msg: + # Some pythons fail getting the argument as an integer, and + # it falls through to the sequence. Seeing this on 32bit windows. + self.assertTrue(True, "Sequence required") except MemoryError as msg: self.assertTrue(msg) except: