diff --git a/PIL/Image.py b/PIL/Image.py index 333397701..e33454d90 100644 --- a/PIL/Image.py +++ b/PIL/Image.py @@ -35,6 +35,12 @@ class _imaging_not_installed: def __getattr__(self, id): raise ImportError("The _imaging C module is not installed") + +class ImageIsTooBigError(Exception): + pass + +ARBITARY_LARGE_LIMIT = 6000 * 6000 - 1 # FIXME: Pick sensible limit + try: # give Tk a chance to set up the environment, in case we're # using an _imaging module linked against libtcl/libtk (use @@ -101,7 +107,7 @@ import collections import numbers # works everywhere, win for pypy, not cpython -USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') +USE_CFFI_ACCESS = hasattr(sys, 'pypy_version_info') try: import cffi HAS_CFFI=True @@ -233,7 +239,7 @@ _MODE_CONV = { "CMYK": ('|u1', 4), "YCbCr": ('|u1', 3), "LAB": ('|u1', 3), # UNDONE - unsigned |u1i1i1 - # I;16 == I;16L, and I;32 == I;32L + # I;16 == I;16L, and I;32 == I;32L "I;16": ('u2', None), "I;16L": (' 8bit images. + # a gamma function point transform on > 8bit images. scale, offset = _getscaleoffset(lut) return self._new(self.im.point_transform(scale, offset)) # for other modes, convert the function to a table @@ -1420,8 +1426,8 @@ class Image: self._copy() self.pyaccess = None self.load() - - if self.pyaccess: + + if self.pyaccess: return self.pyaccess.putpixel(xy,value) return self.im.putpixel(xy, value) @@ -2100,7 +2106,18 @@ _fromarray_typemap[((1, 1), _ENDIAN + "i4")] = ("I", "I") _fromarray_typemap[((1, 1), _ENDIAN + "f4")] = ("F", "F") -def open(fp, mode="r"): +def _compression_bomb_check(im, maximum_pixels): + if maximum_pixels is None: + return + + pixels = im.size[0] * im.size[1] + print("Pixels:", pixels) # FIXME: temporary + + if im.size[0] * im.size[1] > maximum_pixels: + raise ImageIsTooBigError("Image size exceeds limit") + + +def open(fp, mode="r", maximum_pixels=ARBITARY_LARGE_LIMIT): """ Opens and identifies the given image file. @@ -2114,6 +2131,7 @@ def open(fp, mode="r"): must implement :py:meth:`~file.read`, :py:meth:`~file.seek`, and :py:meth:`~file.tell` methods, and be opened in binary mode. :param mode: The mode. If given, this argument must be "r". + :param maximum_pixels: TODO. :returns: An :py:class:`~PIL.Image.Image` object. :exception IOError: If the file cannot be found, or the image cannot be opened and identified. @@ -2137,7 +2155,10 @@ def open(fp, mode="r"): factory, accept = OPEN[i] if not accept or accept(prefix): fp.seek(0) - return factory(fp, filename) + # return factory(fp, filename) + im = factory(fp, filename) + _compression_bomb_check(im, maximum_pixels) + return im except (SyntaxError, IndexError, TypeError): #import traceback #traceback.print_exc() @@ -2150,7 +2171,10 @@ def open(fp, mode="r"): factory, accept = OPEN[i] if not accept or accept(prefix): fp.seek(0) - return factory(fp, filename) + # return factory(fp, filename) + im = factory(fp, filename) + _compression_bomb_check(im, maximum_pixels) + return im except (SyntaxError, IndexError, TypeError): #import traceback #traceback.print_exc()