| |
@@ -0,0 +1,202 @@
|
| |
+ From ad4d2a2584e3d53ecbe7c691fff2f3e46fe8bca7 Mon Sep 17 00:00:00 2001
|
| |
+ From: Sam Bull <git@sambull.org>
|
| |
+ Date: Thu, 4 Apr 2024 18:25:36 +0100
|
| |
+ Subject: [PATCH 1/4] Create 8292.feature.rst
|
| |
+
|
| |
+ ---
|
| |
+ CHANGES/8292.feature.rst | 1 +
|
| |
+ 1 file changed, 1 insertion(+)
|
| |
+ create mode 100644 CHANGES/8292.feature.rst
|
| |
+
|
| |
+ diff --git a/CHANGES/8292.feature.rst b/CHANGES/8292.feature.rst
|
| |
+ new file mode 100644
|
| |
+ index 00000000..782449e4
|
| |
+ --- /dev/null
|
| |
+ +++ b/CHANGES/8292.feature.rst
|
| |
+ @@ -0,0 +1 @@
|
| |
+ +Upgraded to LLHTTP 9.2.1 -- by :user:`Dreamsorcerer`.
|
| |
+ --
|
| |
+ 2.44.0
|
| |
+
|
| |
+
|
| |
+ From 5febd9e8749c47ec6ad24c62d5623b690c192018 Mon Sep 17 00:00:00 2001
|
| |
+ From: Sam Bull <git@sambull.org>
|
| |
+ Date: Thu, 4 Apr 2024 23:08:43 +0100
|
| |
+ Subject: [PATCH 2/4] Update test_http_parser.py
|
| |
+
|
| |
+ ---
|
| |
+ tests/test_http_parser.py | 50 ++++++++++++++++++++++++++++++++-------
|
| |
+ 1 file changed, 42 insertions(+), 8 deletions(-)
|
| |
+
|
| |
+ diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py
|
| |
+ index b9317305..bbe14b5b 100644
|
| |
+ --- a/tests/test_http_parser.py
|
| |
+ +++ b/tests/test_http_parser.py
|
| |
+ @@ -108,8 +108,7 @@ def test_c_parser_loaded():
|
| |
+
|
| |
+ def test_parse_headers(parser: Any) -> None:
|
| |
+ text = b"""GET /test HTTP/1.1\r
|
| |
+ -test: line\r
|
| |
+ - continue\r
|
| |
+ +test: a line\r
|
| |
+ test2: data\r
|
| |
+ \r
|
| |
+ """
|
| |
+ @@ -117,13 +116,24 @@ test2: data\r
|
| |
+ assert len(messages) == 1
|
| |
+ msg = messages[0][0]
|
| |
+
|
| |
+ - assert list(msg.headers.items()) == [("test", "line continue"), ("test2", "data")]
|
| |
+ - assert msg.raw_headers == ((b"test", b"line continue"), (b"test2", b"data"))
|
| |
+ + assert list(msg.headers.items()) == [("test", "a line"), ("test2", "data")]
|
| |
+ + assert msg.raw_headers == ((b"test", b"a line"), (b"test2", b"data"))
|
| |
+ assert not msg.should_close
|
| |
+ assert msg.compression is None
|
| |
+ assert not msg.upgrade
|
| |
+
|
| |
+
|
| |
+ +def test_reject_obsolete_line_folding(parser: Any) -> None:
|
| |
+ + text = b"""GET /test HTTP/1.1\r
|
| |
+ +test: line\r
|
| |
+ + Content-Length: 48\r
|
| |
+ +test2: data\r
|
| |
+ +\r
|
| |
+ +"""
|
| |
+ + with pytest.raises(http_exceptions.BadHttpMessage):
|
| |
+ + parser.feed_data(text)
|
| |
+ +
|
| |
+ +
|
| |
+ @pytest.mark.skipif(NO_EXTENSIONS, reason="Only tests C parser.")
|
| |
+ def test_invalid_character(loop: Any, protocol: Any, request: Any) -> None:
|
| |
+ parser = HttpRequestParserC(
|
| |
+ @@ -341,8 +351,8 @@ def test_parse_delayed(parser) -> None:
|
| |
+
|
| |
+ def test_headers_multi_feed(parser) -> None:
|
| |
+ text1 = b"GET /test HTTP/1.1\r\n"
|
| |
+ - text2 = b"test: line\r"
|
| |
+ - text3 = b"\n continue\r\n\r\n"
|
| |
+ + text2 = b"test: line"
|
| |
+ + text3 = b" continue\r\n\r\n"
|
| |
+
|
| |
+ messages, upgrade, tail = parser.feed_data(text1)
|
| |
+ assert len(messages) == 0
|
| |
+ @@ -708,7 +718,7 @@ def test_max_header_value_size_under_limit(parser) -> None:
|
| |
+ @pytest.mark.parametrize("size", [40965, 8191])
|
| |
+ def test_max_header_value_size_continuation(parser, size) -> None:
|
| |
+ name = b"T" * (size - 5)
|
| |
+ - text = b"GET /test HTTP/1.1\r\n" b"data: test\r\n " + name + b"\r\n\r\n"
|
| |
+ + text = b"GET /test HTTP/1.1\r\n" b"data: test " + name + b"\r\n\r\n"
|
| |
+
|
| |
+ match = f"400, message:\n Got more than 8190 bytes \\({size}\\) when reading"
|
| |
+ with pytest.raises(http_exceptions.LineTooLong, match=match):
|
| |
+ @@ -717,7 +727,7 @@ def test_max_header_value_size_continuation(parser, size) -> None:
|
| |
+
|
| |
+ def test_max_header_value_size_continuation_under_limit(parser) -> None:
|
| |
+ value = b"A" * 8185
|
| |
+ - text = b"GET /test HTTP/1.1\r\n" b"data: test\r\n " + value + b"\r\n\r\n"
|
| |
+ + text = b"GET /test HTTP/1.1\r\n" b"data: test " + value + b"\r\n\r\n"
|
| |
+
|
| |
+ messages, upgrade, tail = parser.feed_data(text)
|
| |
+ msg = messages[0][0]
|
| |
+ @@ -971,6 +981,30 @@ def test_http_response_parser_utf8_without_reason(response: Any) -> None:
|
| |
+ assert not tail
|
| |
+
|
| |
+
|
| |
+ +def test_http_response_parser_obs_line_folding(response: Any) -> None:
|
| |
+ + text = b"HTTP/1.1 200 Ok\r\ntest: line\r\n continue\r\n\r\n"
|
| |
+ +
|
| |
+ + messages, upgraded, tail = response.feed_data(text)
|
| |
+ + assert len(messages) == 1
|
| |
+ + msg = messages[0][0]
|
| |
+ +
|
| |
+ + assert msg.version == (1, 1)
|
| |
+ + assert msg.code == 200
|
| |
+ + assert msg.reason == "Ok"
|
| |
+ + assert msg.headers == CIMultiDict([("TEST", "line continue")])
|
| |
+ + assert msg.raw_headers == ((b"test", b"line continue"),)
|
| |
+ + assert not upgraded
|
| |
+ + assert not tail
|
| |
+ +
|
| |
+ +
|
| |
+ +@pytest.mark.dev_mode
|
| |
+ +def test_http_response_parser_strict_obs_line_folding(response: Any) -> None:
|
| |
+ + text = b"HTTP/1.1 200 Ok\r\ntest: line\r\n continue\r\n\r\n"
|
| |
+ +
|
| |
+ + with pytest.raises(http_exceptions.BadHttpMessage):
|
| |
+ + response.feed_data(text)
|
| |
+ +
|
| |
+ +
|
| |
+ @pytest.mark.parametrize("size", [40962, 8191])
|
| |
+ def test_http_response_parser_bad_status_line_too_long(response, size) -> None:
|
| |
+ reason = b"t" * (size - 2)
|
| |
+ --
|
| |
+ 2.44.0
|
| |
+
|
| |
+
|
| |
+ From 5fcecdc3edd50a0dbe07a53efdb1dcc7e1545dc8 Mon Sep 17 00:00:00 2001
|
| |
+ From: Sam Bull <git@sambull.org>
|
| |
+ Date: Thu, 4 Apr 2024 23:16:25 +0100
|
| |
+ Subject: [PATCH 3/4] Update http_parser.py
|
| |
+
|
| |
+ ---
|
| |
+ aiohttp/http_parser.py | 6 ++++--
|
| |
+ 1 file changed, 4 insertions(+), 2 deletions(-)
|
| |
+
|
| |
+ diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py
|
| |
+ index 1877f558..4e25c111 100644
|
| |
+ --- a/aiohttp/http_parser.py
|
| |
+ +++ b/aiohttp/http_parser.py
|
| |
+ @@ -126,10 +126,12 @@ class HeadersParser:
|
| |
+ max_line_size: int = 8190,
|
| |
+ max_headers: int = 32768,
|
| |
+ max_field_size: int = 8190,
|
| |
+ + lax: bool = False
|
| |
+ ) -> None:
|
| |
+ self.max_line_size = max_line_size
|
| |
+ self.max_headers = max_headers
|
| |
+ self.max_field_size = max_field_size
|
| |
+ + self._lax = lax
|
| |
+
|
| |
+ def parse_headers(
|
| |
+ self, lines: List[bytes]
|
| |
+ @@ -176,7 +178,7 @@ class HeadersParser:
|
| |
+ line = lines[lines_idx]
|
| |
+
|
| |
+ # consume continuation lines
|
| |
+ - continuation = line and line[0] in (32, 9) # (' ', '\t')
|
| |
+ + continuation = self._lax and line and line[0] in (32, 9) # (' ', '\t')
|
| |
+
|
| |
+ # Deprecated: https://www.rfc-editor.org/rfc/rfc9112.html#name-obsolete-line-folding
|
| |
+ if continuation:
|
| |
+ @@ -266,7 +268,7 @@ class HttpParser(abc.ABC, Generic[_MsgT]):
|
| |
+ self._payload_parser: Optional[HttpPayloadParser] = None
|
| |
+ self._auto_decompress = auto_decompress
|
| |
+ self._limit = limit
|
| |
+ - self._headers_parser = HeadersParser(max_line_size, max_headers, max_field_size)
|
| |
+ + self._headers_parser = HeadersParser(max_line_size, max_headers, max_field_size, self.lax)
|
| |
+
|
| |
+ @abc.abstractmethod
|
| |
+ def parse_message(self, lines: List[bytes]) -> _MsgT:
|
| |
+ --
|
| |
+ 2.44.0
|
| |
+
|
| |
+
|
| |
+ From deaf7786bb88a82b22dda9c4d8bca5fa51adbc39 Mon Sep 17 00:00:00 2001
|
| |
+ From: Sam Bull <git@sambull.org>
|
| |
+ Date: Thu, 4 Apr 2024 23:18:01 +0100
|
| |
+ Subject: [PATCH 4/4] Update 8292.feature.rst
|
| |
+
|
| |
+ ---
|
| |
+ CHANGES/8292.feature.rst | 2 +-
|
| |
+ 1 file changed, 1 insertion(+), 1 deletion(-)
|
| |
+
|
| |
+ diff --git a/CHANGES/8292.feature.rst b/CHANGES/8292.feature.rst
|
| |
+ index 782449e4..db83aa7e 100644
|
| |
+ --- a/CHANGES/8292.feature.rst
|
| |
+ +++ b/CHANGES/8292.feature.rst
|
| |
+ @@ -1 +1 @@
|
| |
+ -Upgraded to LLHTTP 9.2.1 -- by :user:`Dreamsorcerer`.
|
| |
+ +Upgraded to LLHTTP 9.2.1, and started rejected obsolete line folding in Python parser to match -- by :user:`Dreamsorcerer`.
|
| |
+ --
|
| |
+ 2.44.0
|
| |
+
|
| |
To be merged and built in a side tag with https://src.fedoraproject.org/rpms/llhttp/pull-request/26.
This will be released upstream in 3.9.4, hopefully soon.
Currently testing in COPR.