From: Ben Darnell Date: Sun, 14 Apr 2013 00:35:24 +0000 (-0400) Subject: Handle malformed headers more gracefully. X-Git-Tag: v3.1.0~117 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8ca13ef006b9d223d9e63d416318a2d11fe17754;p=thirdparty%2Ftornado.git Handle malformed headers more gracefully. Closes #699. --- diff --git a/tornado/httpserver.py b/tornado/httpserver.py index cfc2a5175..16472fa44 100644 --- a/tornado/httpserver.py +++ b/tornado/httpserver.py @@ -294,7 +294,11 @@ class HTTPConnection(object): raise _BadRequestException("Malformed HTTP request line") if not version.startswith("HTTP/"): raise _BadRequestException("Malformed HTTP version in HTTP Request-Line") - headers = httputil.HTTPHeaders.parse(data[eol:]) + try: + headers = httputil.HTTPHeaders.parse(data[eol:]) + except ValueError: + # Probably from split() if there was no ':' in the line + raise _BadRequestException("Malformed HTTP headers") # HTTPRequest wants an IP, not a full socket address if self.address_family in (socket.AF_INET, socket.AF_INET6): diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index 54b38b464..ba23a15ba 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -341,14 +341,44 @@ class HTTPServerTest(AsyncHTTPTestCase): self.assertEqual(200, response.code) self.assertEqual(json_decode(response.body), {}) - def test_empty_request(self): - stream = IOStream(socket.socket(), io_loop=self.io_loop) - stream.connect(('localhost', self.get_http_port()), self.stop) + +class HTTPServerRawTest(AsyncHTTPTestCase): + def get_app(self): + return Application([ + ('/echo', EchoHandler), + ]) + + def setUp(self): + super(HTTPServerRawTest, self).setUp() + self.stream = IOStream(socket.socket()) + self.stream.connect(('localhost', self.get_http_port()), self.stop) self.wait() - stream.close() + + def tearDown(self): + self.stream.close() + super(HTTPServerRawTest, self).tearDown() + + def test_empty_request(self): + self.stream.close() self.io_loop.add_timeout(datetime.timedelta(seconds=0.001), self.stop) self.wait() + def test_malformed_first_line(self): + with ExpectLog(gen_log, '.*Malformed HTTP request line'): + self.stream.write(b'asdf\r\n\r\n') + # TODO: need an async version of ExpectLog so we don't need + # hard-coded timeouts here. + self.io_loop.add_timeout(datetime.timedelta(seconds=0.01), + self.stop) + self.wait() + + def test_malformed_headers(self): + with ExpectLog(gen_log, '.*Malformed HTTP headers'): + self.stream.write(b'GET / HTTP/1.0\r\nasdf\r\n\r\n') + self.io_loop.add_timeout(datetime.timedelta(seconds=0.01), + self.stop) + self.wait() + class XHeaderTest(HandlerBaseTestCase): class Handler(RequestHandler):