From ca5c6db72ff84dfefd292d6f2bf13f32fa5aecd5 Mon Sep 17 00:00:00 2001 From: Ben Kallus Date: Mon, 16 Oct 2023 10:47:54 -0400 Subject: [PATCH 1/3] Add check to validate absolute URIs --- CHANGES/7712.bugfix | 1 + aiohttp/http_parser.py | 6 ++++++ tests/test_http_parser.py | 5 +++++ 3 files changed, 12 insertions(+) create mode 100644 CHANGES/7712.bugfix diff --git a/CHANGES/7712.bugfix b/CHANGES/7712.bugfix new file mode 100644 index 00000000000..b5304c34ac2 --- /dev/null +++ b/CHANGES/7712.bugfix @@ -0,0 +1 @@ +Add check to validate that absolute URIs have schemes. diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py index 4dd615ad389..76dc35ce635 100644 --- a/aiohttp/http_parser.py +++ b/aiohttp/http_parser.py @@ -578,10 +578,16 @@ def parse_message(self, lines: List[bytes]) -> RawRequestMessage: fragment=url_fragment, encoded=True, ) + elif path == "*" and method == "OPTIONS": + # asterisk-form, + url = URL(path, encoded=True) else: # absolute-form for proxy maybe, # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2 url = URL(path, encoded=True) + if url.scheme == "": + # not absolute-form + raise BadStatusLine(line) # read headers ( diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index 4ed27e67ea4..9ca3a3eedd8 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -740,6 +740,11 @@ def test_http_request_parser_bad_version_number(parser: Any) -> None: parser.feed_data(b"GET /test HTTP/1.32\r\n\r\n") +def test_http_request_parser_bad_uri(parser: Any) -> None: + with pytest.raises(http_exceptions.BadStatusLine): + parser.feed_data(b"GET ! HTTP/1.1\r\n\r\n") + + @pytest.mark.parametrize("size", [40965, 8191]) def test_http_request_max_status_line(parser: Any, size: Any) -> None: path = b"t" * (size - 5) From f8a9d6b079e58c53bf3a2c02d8587cd105f01019 Mon Sep 17 00:00:00 2001 From: Ben Kallus Date: Mon, 16 Oct 2023 11:13:02 -0400 Subject: [PATCH 2/3] change exception type --- aiohttp/http_parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py index 76dc35ce635..3eef05020f6 100644 --- a/aiohttp/http_parser.py +++ b/aiohttp/http_parser.py @@ -34,6 +34,7 @@ ContentEncodingError, ContentLengthError, InvalidHeader, + InvalidURLError, LineTooLong, TransferEncodingError, ) @@ -587,7 +588,7 @@ def parse_message(self, lines: List[bytes]) -> RawRequestMessage: url = URL(path, encoded=True) if url.scheme == "": # not absolute-form - raise BadStatusLine(line) + raise InvalidURLError(line) # read headers ( From 994031acad7215a75041a6f8a62c60563551aaf1 Mon Sep 17 00:00:00 2001 From: Ben Kallus Date: Mon, 16 Oct 2023 11:40:49 -0400 Subject: [PATCH 3/3] update test to reflect corrected error type --- tests/test_http_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index 9ca3a3eedd8..a234a895fe2 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -741,7 +741,7 @@ def test_http_request_parser_bad_version_number(parser: Any) -> None: def test_http_request_parser_bad_uri(parser: Any) -> None: - with pytest.raises(http_exceptions.BadStatusLine): + with pytest.raises(http_exceptions.InvalidURLError): parser.feed_data(b"GET ! HTTP/1.1\r\n\r\n")