]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Handle malformed headers more gracefully.
authorBen Darnell <ben@bendarnell.com>
Sun, 14 Apr 2013 00:35:24 +0000 (20:35 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 14 Apr 2013 00:35:24 +0000 (20:35 -0400)
Closes #699.

tornado/httpserver.py
tornado/test/httpserver_test.py

index cfc2a5175d7d63ede799e7a42049f32a2741f24e..16472fa44d23f76cafd7315280de95c5cf33b6c7 100644 (file)
@@ -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):
index 54b38b464c03c3c1c4185d96dea8329f03c5b96c..ba23a15baf7bfaf85a2e7e7ec88c194cbae781dd 100644 (file)
@@ -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):