From 9ffdefda0325f37722916816b81f6613f8129361 Mon Sep 17 00:00:00 2001 From: Pierce Lopez Date: Mon, 25 Dec 2017 22:11:26 -0500 Subject: [PATCH] http: read final crlf of chunked requests otherwise a subsequent request on the same connection will fail to be parsed thanks to @eeelin for the bug report --- tornado/http1connection.py | 3 +++ tornado/test/httpserver_test.py | 7 +++++-- tornado/test/web_test.py | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tornado/http1connection.py b/tornado/http1connection.py index de8d8bf38..331386a15 100644 --- a/tornado/http1connection.py +++ b/tornado/http1connection.py @@ -599,6 +599,9 @@ class HTTP1Connection(httputil.HTTPConnection): chunk_len = yield self.stream.read_until(b"\r\n", max_bytes=64) chunk_len = int(chunk_len.strip(), 16) if chunk_len == 0: + crlf = yield self.stream.read_bytes(2) + if crlf != b'\r\n': + raise HTTPInputError("improperly terminated chunked request") return total_size += chunk_len if total_size > self._max_body_size: diff --git a/tornado/test/httpserver_test.py b/tornado/test/httpserver_test.py index 1b1286022..3b0524940 100644 --- a/tornado/test/httpserver_test.py +++ b/tornado/test/httpserver_test.py @@ -808,9 +808,12 @@ class KeepAliveTest(AsyncHTTPTestCase): def test_keepalive_chunked(self): self.http_version = b'HTTP/1.0' self.connect() - self.stream.write(b'POST / HTTP/1.0\r\nConnection: keep-alive\r\n' + self.stream.write(b'POST / HTTP/1.0\r\n' + b'Connection: keep-alive\r\n' b'Transfer-Encoding: chunked\r\n' - b'\r\n0\r\n') + b'\r\n' + b'0\r\n' + b'\r\n') self.read_response() self.assertEqual(self.headers['Connection'], 'Keep-Alive') self.stream.write(b'GET / HTTP/1.0\r\nConnection: keep-alive\r\n\r\n') diff --git a/tornado/test/web_test.py b/tornado/test/web_test.py index 7e3ac7c25..46390e0d1 100644 --- a/tornado/test/web_test.py +++ b/tornado/test/web_test.py @@ -2138,7 +2138,7 @@ class StreamingRequestBodyTest(WebTestCase): stream.write(b"4\r\nqwer\r\n") data = yield self.data self.assertEquals(data, b"qwer") - stream.write(b"0\r\n") + stream.write(b"0\r\n\r\n") yield self.finished data = yield gen.Task(stream.read_until_close) # This would ideally use an HTTP1Connection to read the response. -- 2.47.2