From 8c128d4f042ca36ebdc55ecdd76099b7722331ba Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 22:42:08 +0100 Subject: [PATCH] [PR #7651/45f98b7d backport][3.8] Fix BadStatusLine message (#7666) **This is a backport of PR #7651 as merged into master (45f98b7d5b1aacf21a6cf446a5df51ee2ea2b4b7).** --- CHANGES/7651.bugfix | 1 + aiohttp/_http_parser.pyx | 30 +++++++++++------------------- aiohttp/http_exceptions.py | 4 ++-- tests/test_http_parser.py | 4 +++- 4 files changed, 17 insertions(+), 22 deletions(-) create mode 100644 CHANGES/7651.bugfix diff --git a/CHANGES/7651.bugfix b/CHANGES/7651.bugfix new file mode 100644 index 00000000000..bc013ecf5fa --- /dev/null +++ b/CHANGES/7651.bugfix @@ -0,0 +1 @@ +Fixed display of ``BadStatusLine`` messages from ``llhttp`` -- by :user:`Dreamsorcerer` diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx index 2b4b844d05e..3f28fbdab43 100644 --- a/aiohttp/_http_parser.pyx +++ b/aiohttp/_http_parser.pyx @@ -2,7 +2,6 @@ # # Based on https://github.com/MagicStack/httptools # -from __future__ import absolute_import, print_function from cpython cimport ( Py_buffer, @@ -813,7 +812,9 @@ cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): cdef cparser.llhttp_errno_t errno = cparser.llhttp_get_errno(parser) cdef bytes desc = cparser.llhttp_get_error_reason(parser) - if errno in (cparser.HPE_CB_MESSAGE_BEGIN, + err_msg = "{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer) + + if errno in {cparser.HPE_CB_MESSAGE_BEGIN, cparser.HPE_CB_HEADERS_COMPLETE, cparser.HPE_CB_MESSAGE_COMPLETE, cparser.HPE_CB_CHUNK_HEADER, @@ -823,22 +824,13 @@ cdef parser_error_from_errno(cparser.llhttp_t* parser, data, pointer): cparser.HPE_INVALID_CONTENT_LENGTH, cparser.HPE_INVALID_CHUNK_SIZE, cparser.HPE_INVALID_EOF_STATE, - cparser.HPE_INVALID_TRANSFER_ENCODING): - cls = BadHttpMessage - - elif errno == cparser.HPE_INVALID_STATUS: - cls = BadStatusLine - - elif errno == cparser.HPE_INVALID_METHOD: - cls = BadStatusLine - - elif errno == cparser.HPE_INVALID_VERSION: - cls = BadStatusLine - + cparser.HPE_INVALID_TRANSFER_ENCODING}: + return BadHttpMessage(err_msg) + elif errno in {cparser.HPE_INVALID_STATUS, + cparser.HPE_INVALID_METHOD, + cparser.HPE_INVALID_VERSION}: + return BadStatusLine(error=err_msg) elif errno == cparser.HPE_INVALID_URL: - cls = InvalidURLError - - else: - cls = BadHttpMessage + return InvalidURLError(err_msg) - return cls("{}:\n\n {!r}\n {}".format(desc.decode("latin-1"), data, pointer)) + return BadHttpMessage(err_msg) diff --git a/aiohttp/http_exceptions.py b/aiohttp/http_exceptions.py index b5d16ea4ec1..63c20af3d96 100644 --- a/aiohttp/http_exceptions.py +++ b/aiohttp/http_exceptions.py @@ -95,10 +95,10 @@ def __init__(self, hdr: Union[bytes, str]) -> None: class BadStatusLine(BadHttpMessage): - def __init__(self, line: str = "") -> None: + def __init__(self, line: str = "", error: Optional[str] = None) -> None: if not isinstance(line, str): line = repr(line) - super().__init__(f"Bad status line {line!r}") + super().__init__(error or f"Bad status line {line!r}") self.args = (line,) self.line = line diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index b742157d149..4b185c9e6b1 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -649,8 +649,10 @@ def test_http_request_parser(parser) -> None: def test_http_request_bad_status_line(parser) -> None: text = b"getpath \r\n\r\n" - with pytest.raises(http_exceptions.BadStatusLine): + with pytest.raises(http_exceptions.BadStatusLine) as exc_info: parser.feed_data(text) + # Check for accidentally escaped message. + assert r"\n" not in exc_info.value.message def test_http_request_upgrade(parser) -> None: