Skip to content

Commit

Permalink
Merge pull request #614 from gi11es/master
Browse files Browse the repository at this point in the history
Avoid image bombs by having a pixel count limit
  • Loading branch information
masom committed Nov 19, 2015
2 parents 4bfb5ab + 78427d2 commit 054a9bc
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
27 changes: 22 additions & 5 deletions tests/handlers/test_base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,9 @@ def test_should_not_convert_webp_if_already_webp(self):
expect(response.headers).not_to_include('Vary')
expect(response.body).to_be_webp()

def test_should_not_convert_webp_if_bigger_than_89478485_pixels(self):
def test_should_error_if_bigger_than_75_megapixels(self):
response = self.get_as_webp('/unsafe/16384.png')

expect(response.code).to_equal(200)
expect(response.headers).not_to_include('Vary')
expect(response.body).to_be_png()
expect(response.code).to_equal(500)

def test_should_not_convert_animated_gifs_to_webp(self):
response = self.get_as_webp('/unsafe/animated_image.gif')
Expand Down Expand Up @@ -661,3 +658,23 @@ def test_should_be_ok_but_150x150(self):
expect(response.code).to_equal(200)
expect(response.headers['Content-Type']).to_equal('image/jpeg')
expect(engine.size).to_equal((150, 150))

class ImageOperationsWithMaxPixels(BaseImagingTestCase):
def get_context(self):
cfg = Config(SECURITY_KEY='ACME-SEC')
cfg.LOADER = "thumbor.loaders.file_loader"
cfg.FILE_LOADER_ROOT_PATH = self.loader_path
cfg.STORAGE = "thumbor.storages.no_storage"
cfg.MAX_PIXELS = 1000

importer = Importer(cfg)
importer.import_modules()
server = ServerParameters(8889, 'localhost', 'thumbor.conf', None, 'info', None)
server.security_key = 'ACME-SEC'
ctx = Context(server, cfg, importer)
ctx.server.gifsicle_path = which('gifsicle')
return ctx

def test_should_error(self):
response = self.fetch('/unsafe/200x200/wellsford.jpg')
expect(response.code).to_equal(500)
1 change: 1 addition & 0 deletions thumbor/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

Config.define('MAX_WIDTH', 0, "Max width in pixels for images read or generated by thumbor", 'Imaging')
Config.define('MAX_HEIGHT', 0, "Max height in pixels for images read or generated by thumbor", 'Imaging')
Config.define('MAX_PIXELS', 75e6, "Max pixel count for images read by thumbor", "Imaging")
Config.define('MIN_WIDTH', 1, "Min width in pixels for images read or generated by thumbor", 'Imaging')
Config.define('MIN_HEIGHT', 1, "Min width in pixels for images read or generated by thumbor", 'Imaging')
Config.define('ALLOWED_SOURCES', [], "Allowed domains for the http loader to download. These are regular expressions.", 'Imaging')
Expand Down
6 changes: 6 additions & 0 deletions thumbor/engines/pil.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# http://www.opensource.org/licenses/mit-license
# Copyright (c) 2011 globo.com timehome@corp.globo.com

import warnings
import os
from tempfile import mkstemp
from subprocess import Popen, PIPE
Expand Down Expand Up @@ -47,6 +48,11 @@ def __init__(self, context):
self.subsampling = None
self.qtables = None

if self.context and self.context.config.MAX_PIXELS:
Image.MAX_IMAGE_PIXELS = self.context.config.MAX_PIXELS
# Error on Image.open when image pixel count is above MAX_IMAGE_PIXELS
warnings.simplefilter('error', Image.DecompressionBombWarning)

def gen_image(self, size, color):
if color == 'transparent':
color = None
Expand Down

0 comments on commit 054a9bc

Please sign in to comment.