diff --git a/marconi/tests/transport/wsgi/test_messages.py b/marconi/tests/transport/wsgi/test_messages.py index 75a60a174..570e71677 100644 --- a/marconi/tests/transport/wsgi/test_messages.py +++ b/marconi/tests/transport/wsgi/test_messages.py @@ -119,6 +119,15 @@ class MessagesBaseTest(base.TestBase): self.assertEquals(self.srmock.status, falcon.HTTP_400) + def test_unsupported_json(self): + for document in ('{"overflow": 9223372036854775808}', + '{"underflow": -9223372036854775809}'): + self.simulate_post(self.queue_path + '/messages', + body=document, + headers=self.headers) + + self.assertEquals(self.srmock.status, falcon.HTTP_400) + def test_delete(self): path = self.queue_path + '/messages' self._post_messages(path) diff --git a/marconi/transport/helpers.py b/marconi/transport/helpers.py index bb7771570..f052f3d8f 100644 --- a/marconi/transport/helpers.py +++ b/marconi/transport/helpers.py @@ -21,6 +21,20 @@ class MalformedJSON(ValueError): pass +class OverflowedJSONInteger(OverflowError): + """JSON integer is too large.""" + pass + + +def _json_int(s): + """Parse a string as a base 10 64-bit signed integer.""" + i = int(s) + if not (int(-2 ** 63) <= i <= int(2 ** 63 - 1)): + raise OverflowedJSONInteger() + + return i + + def read_json(stream, len): """Like json.load, but converts ValueError to MalformedJSON upon failure. @@ -28,7 +42,7 @@ def read_json(stream, len): :param len: the number of bytes to read from stream """ try: - return json.loads(stream.read(len)) + return json.loads(stream.read(len), parse_int=_json_int) except ValueError as ex: raise MalformedJSON(ex) diff --git a/marconi/transport/wsgi/helpers.py b/marconi/transport/wsgi/helpers.py index 930f95499..efc78eb4e 100644 --- a/marconi/transport/wsgi/helpers.py +++ b/marconi/transport/wsgi/helpers.py @@ -62,6 +62,11 @@ def filter_stream(stream, len, spec, doctype=JSONObject): description = _('Body could not be parsed.') raise exceptions.HTTPBadRequestBody(description) + except helpers.OverflowedJSONInteger as ex: + LOG.exception(ex) + description = _('JSON contains integer that is too large.') + raise exceptions.HTTPBadRequestBody(description) + except Exception as ex: # Error while reading from the network/server LOG.exception(ex)