diff --git a/Tests/images/l2rgb_read.bmp b/Tests/images/l2rgb_read.bmp new file mode 100644 index 000000000..838e3226b Binary files /dev/null and b/Tests/images/l2rgb_read.bmp differ diff --git a/Tests/test_map.py b/Tests/test_map.py new file mode 100644 index 000000000..235bfadbc --- /dev/null +++ b/Tests/test_map.py @@ -0,0 +1,25 @@ +from helper import PillowTestCase, unittest + +from PIL import Image + +class TestMap(PillowTestCase): + def test_overflow(self): + # There is the potential to overflow comparisons in map.c + # if there are > SIZE_MAX bytes in the image or if + # the file encodes an offset that makes + # (offset + size(bytes)) > SIZE_MAX + + # Note that this image triggers the decompression bomb warning: + max_pixels = Image.MAX_IMAGE_PIXELS + Image.MAX_IMAGE_PIXELS = None + + # This image hits the offset test. + im = Image.open('Tests/images/l2rgb_read.bmp') + with self.assertRaises((ValueError, MemoryError)): + im.load() + + Image.MAX_IMAGE_PIXELS = max_pixels + + +if __name__ == '__main__': + unittest.main() diff --git a/map.c b/map.c index 7309a7bd7..3637ee86a 100644 --- a/map.c +++ b/map.c @@ -342,8 +342,18 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args) stride = xsize * 4; } + if (ysize > INT_MAX / stride) { + PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize"); + return NULL; + } + size = (Py_ssize_t) ysize * stride; + if (offset > SIZE_MAX - size) { + PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset"); + return NULL; + } + /* check buffer size */ if (PyImaging_GetBuffer(target, &view) < 0) return NULL;