diff --git a/PIL/Image.py b/PIL/Image.py index 84fdaba8e..8d4d9c8a8 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -36,6 +36,8 @@ logger = logging.getLogger(__name__) class DecompressionBombWarning(RuntimeWarning): pass +class DecompressionBombError(Exception): + pass class _imaging_not_installed(object): # module placeholder @@ -2493,6 +2495,12 @@ def _decompression_bomb_check(size): pixels = size[0] * size[1] + if pixels > 2 * MAX_IMAGE_PIXELS: + raise DecompressionBombError( + "Image size (%d pixels) exceeds limit of %d pixels, " + "could be decompression bomb DOS attack." % + (pixels, 2* MAX_IMAGE_PIXELS)) + if pixels > MAX_IMAGE_PIXELS: warnings.warn( "Image size (%d pixels) exceeds limit of %d pixels, " diff --git a/Tests/test_decompression_bomb.py b/Tests/test_decompression_bomb.py index 2dc84950a..4da8760cd 100644 --- a/Tests/test_decompression_bomb.py +++ b/Tests/test_decompression_bomb.py @@ -29,20 +29,26 @@ class TestDecompressionBomb(PillowTestCase): Image.open(TEST_FILE) def test_warning(self): - # Arrange - # Set limit to a low, easily testable value - Image.MAX_IMAGE_PIXELS = 10 - self.assertEqual(Image.MAX_IMAGE_PIXELS, 10) + # Set limit to trigger warning on the test file + Image.MAX_IMAGE_PIXELS = 128 * 128 -1 + self.assertEqual(Image.MAX_IMAGE_PIXELS, 128 * 128 - 1) - # Act / Assert self.assert_warning(Image.DecompressionBombWarning, Image.open, TEST_FILE) + def test_exception(self): + # Set limit to trigger exception on the test file + Image.MAX_IMAGE_PIXELS = 64 * 128 -1 + self.assertEqual(Image.MAX_IMAGE_PIXELS, 64 * 128 - 1) + + self.assertRaises(Image.DecompressionBombError, + lambda: Image.open(TEST_FILE)) + class TestDecompressionCrop(PillowTestCase): def setUp(self): self.src = hopper() - Image.MAX_IMAGE_PIXELS = self.src.height * self.src.width + Image.MAX_IMAGE_PIXELS = self.src.height * self.src.width * 4 - 1 def tearDown(self): Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT @@ -54,5 +60,6 @@ class TestDecompressionCrop(PillowTestCase): self.assert_warning(Image.DecompressionBombWarning, self.src.crop, box) + if __name__ == '__main__': unittest.main()