From 7df34bd00852ecbacde2cc7d81accd8d82d29d72 Mon Sep 17 00:00:00 2001 From: Chad Whitacre Date: Mon, 20 Mar 2017 15:37:58 -0400 Subject: [PATCH] Hard-cap image size to 256 kB --- .gitignore | 1 + setup.py | 3 +++ tests/image.jpg | Bin 0 -> 20887 bytes tests/test_v1.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++ www/v1.spt | 47 ++++++++++++++++++++++++++++++++---- 5 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 setup.py create mode 100644 tests/image.jpg create mode 100644 tests/test_v1.py diff --git a/.gitignore b/.gitignore index 0a764a4..c182e37 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ env +*.egg-info diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..94551df --- /dev/null +++ b/setup.py @@ -0,0 +1,3 @@ +from setuptools import setup, find_packages + +setup(name='gip', packages=find_packages()) diff --git a/tests/image.jpg b/tests/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a3dc2b37554846b2deab03d61add68c71a7a60c6 GIT binary patch literal 20887 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 QiNk<^MOK0p1^J)<*{xuOrvLx| literal 0 HcmV?d00001 diff --git a/tests/test_v1.py b/tests/test_v1.py new file mode 100644 index 0000000..f9956ba --- /dev/null +++ b/tests/test_v1.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +from cStringIO import StringIO +from os.path import join +from zipfile import ZipFile + +import pytest +from aspen.testing.client import Client +from gip import website + + +@pytest.fixture +def client(): + client = Client(www_root='www', project_root='.') + client._website = website + yield client + +@pytest.fixture +def image(): + yield open(join('tests', 'image.jpg')).read() + + +def zipfile(raw): + return ZipFile(StringIO(raw), mode='r') + +def filenames(zipfile): + return [n.filename for n in zipfile.filelist] + +@pytest.fixture +def vary_length(client, image): + def vary_length(length, fail=True): + method = client.PxST if fail else client.POST + return method( '/v1' + , body=image + , content_type='image/jpeg' + , HTTP_CONTENT_LENGTH=str(length) + ).code + return vary_length + + +def test_normal_case_is_200(client, image): + response = client.POST('/v1', body=image, content_type='image/jpeg') + assert response.code == 200 + assert filenames(zipfile(response.body)) == ['160', '48'] + +def test_length_too_great_is_413(vary_length): + assert vary_length(262145) == 413 + +def test_length_overstated_is_400(vary_length): + assert vary_length(262144) == 400 + assert vary_length(20888) == 400 + +def test_length_properly_stated_is_200(vary_length): + assert vary_length(20887, False) == 200 + +def test_length_understated_is_400(vary_length): + assert vary_length(20886) == 400 + assert vary_length(1) == 400 + assert vary_length(0) == 400 + assert vary_length(-1) == 400 diff --git a/www/v1.spt b/www/v1.spt index 0602b36..e1b5dae 100644 --- a/www/v1.spt +++ b/www/v1.spt @@ -6,10 +6,44 @@ from aspen import Response from PIL import Image warnings.simplefilter('error', Image.DecompressionBombWarning) + + +MAX_SIZE = 256 * 1024 + + +class CappedStringIO(object): + def __init__(self, fp, target): + self.io = StringIO(fp) + self.seek(0) + self.__nread = 0 + self.__target = target + + def read(self, *a, **kw): + out = self.io.read(*a, **kw) + self.__nread += len(out) + if self.__nread > self.__target: + raise Response(400) + return out + + def reset_nread(self): + self.__nread = 0 + + def check_nread(self): + if self.__nread != self.__target: + raise Response(400) + + def seek(self, *a, **kw): self.io.seek(*a, **kw) + def tell(self, *a, **kw): self.io.tell(*a, **kw) + [---] request.allow('POST') -if int(request.headers['Content-Length']) > 256 * 1024: +length = request.headers['Content-Length'] +try: + length = int(length) +except ValueError: + raise Response(400) +if length > 256 * 1024: raise Response(413) image_type = request.headers['Content-Type'] @@ -17,9 +51,14 @@ if image_type not in ('image/png', 'image/jpeg'): raise Response(415) # Load the image. -fp = StringIO(request.raw_body) -fp.seek(0) -image = Image.open(fp) +fp = CappedStringIO(request.raw_body, length) +try: + image = Image.open(fp) + fp.reset_nread() # open reads *some* data + image.load() # load reads *all* data ... +except IOError: # ... and both can raise IOError for parse errors + raise Response(400) +fp.check_nread() # still need this tho # Crop to a square. w, h = image.size