From 8129d26f3a02faa910ddfa49fc503de692b7bf7c Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 6 Aug 2023 12:55:19 +0000 Subject: [PATCH] [PR #7480/1fb06bbc backport][3.8] Fix error pointer on linebreaks (#7482) **This is a backport of PR #7480 as merged into master (1fb06bbc10a7bd621c694a33137cf16b23b07a02).** Fixes #7468. Co-authored-by: Sam Bull --- CHANGES/7468.bugfix | 1 + aiohttp/_http_parser.pyx | 4 ++-- tests/test_http_parser.py | 22 +++++++++++++++++++++- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 CHANGES/7468.bugfix diff --git a/CHANGES/7468.bugfix b/CHANGES/7468.bugfix new file mode 100644 index 00000000000..3f9c256ca0c --- /dev/null +++ b/CHANGES/7468.bugfix @@ -0,0 +1 @@ +Fixed output of parsing errors on `\n`. -- by :user:`Dreamsorcerer` diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx index 4f39dd0c978..8b7d48245d2 100644 --- a/aiohttp/_http_parser.pyx +++ b/aiohttp/_http_parser.pyx @@ -548,8 +548,8 @@ cdef class HttpParser: else: after = cparser.llhttp_get_error_pos(self._cparser) before = data[:after - self.py_buf.buf] - after_b = after.split(b"\n", 1)[0] - before = before.rsplit(b"\n", 1)[-1] + after_b = after.split(b"\r\n", 1)[0] + before = before.rsplit(b"\r\n", 1)[-1] data = before + after_b pointer = " " * (len(repr(before))-1) + "^" ex = parser_error_from_errno(self._cparser, data, pointer) diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index ca6c32207ce..344d0776633 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -132,7 +132,27 @@ def test_invalid_character(loop: Any, protocol: Any, request: Any) -> None: error_detail = re.escape( r""": - b'Set-Cookie: abc\x01def\r' + b'Set-Cookie: abc\x01def' + ^""" + ) + with pytest.raises(http_exceptions.BadHttpMessage, match=error_detail): + parser.feed_data(text) + + +@pytest.mark.skipif(NO_EXTENSIONS, reason="Only tests C parser.") +def test_invalid_linebreak(loop: Any, protocol: Any, request: Any) -> None: + parser = HttpRequestParserC( + protocol, + loop, + 2**16, + max_line_size=8190, + max_field_size=8190, + ) + text = b"GET /world HTTP/1.1\r\nHost: 127.0.0.1\n\r\n" + error_detail = re.escape( + r""": + + b'Host: 127.0.0.1\n' ^""" ) with pytest.raises(http_exceptions.BadHttpMessage, match=error_detail):