summaryrefslogtreecommitdiffstats
path: root/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-53643.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-53643.patch')
-rw-r--r--meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-53643.patch526
1 files changed, 526 insertions, 0 deletions
diff --git a/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-53643.patch b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-53643.patch
new file mode 100644
index 0000000000..fd8f83d563
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-aiohttp/CVE-2025-53643.patch
@@ -0,0 +1,526 @@
1From 5a3e141bca22757e60b3c584b8ac7eee90708b8b Mon Sep 17 00:00:00 2001
2From: Sam Bull <git@sambull.org>
3Date: Wed, 9 Jul 2025 19:55:22 +0100
4Subject: [PATCH] Add trailer parsing logic (#11269) (#11287)
5
6(cherry picked from commit 7dd4b5535e6bf9c2d2f05fde638517bff065ba74)
7
8CVE-2025-53643.patch
9
10Upstream-Status: Backport
11[https://github.com/aio-libs/aiohttp/commit/e8d774f635dc6d1cd3174d0e38891da5de0e2b6a]
12
13Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
14---
15 CHANGES/11269.feature.rst | 1 +
16 aiohttp/http_parser.py | 70 +++++++++---------
17 aiohttp/multipart.py | 2 +-
18 tests/test_http_parser.py | 148 ++++++++++++++++----------------------
19 4 files changed, 100 insertions(+), 121 deletions(-)
20 create mode 100644 CHANGES/11269.feature.rst
21
22diff --git a/CHANGES/11269.feature.rst b/CHANGES/11269.feature.rst
23new file mode 100644
24index 000000000..92cf173be
25--- /dev/null
26+++ b/CHANGES/11269.feature.rst
27@@ -0,0 +1 @@
28+Added initial trailer parsing logic to Python HTTP parser -- by :user:`Dreamsorcerer`.
29diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py
30index 1b8b5b4d4..7d8db6d6f 100644
31--- a/aiohttp/http_parser.py
32+++ b/aiohttp/http_parser.py
33@@ -142,8 +142,8 @@ class HeadersParser:
34 # note: "raw" does not mean inclusion of OWS before/after the field value
35 raw_headers = []
36
37- lines_idx = 1
38- line = lines[1]
39+ lines_idx = 0
40+ line = lines[lines_idx]
41 line_count = len(lines)
42
43 while line:
44@@ -400,6 +400,7 @@ class HttpParser(abc.ABC, Generic[_MsgT]):
45 response_with_body=self.response_with_body,
46 auto_decompress=self._auto_decompress,
47 lax=self.lax,
48+ headers_parser=self._headers_parser,
49 )
50 if not payload_parser.done:
51 self._payload_parser = payload_parser
52@@ -418,6 +419,7 @@ class HttpParser(abc.ABC, Generic[_MsgT]):
53 compression=msg.compression,
54 auto_decompress=self._auto_decompress,
55 lax=self.lax,
56+ headers_parser=self._headers_parser,
57 )
58 elif not empty_body and length is None and self.read_until_eof:
59 payload = StreamReader(
60@@ -436,6 +438,7 @@ class HttpParser(abc.ABC, Generic[_MsgT]):
61 response_with_body=self.response_with_body,
62 auto_decompress=self._auto_decompress,
63 lax=self.lax,
64+ headers_parser=self._headers_parser,
65 )
66 if not payload_parser.done:
67 self._payload_parser = payload_parser
68@@ -473,6 +476,10 @@ class HttpParser(abc.ABC, Generic[_MsgT]):
69
70 eof = True
71 data = b""
72+ if isinstance(
73+ underlying_exc, (InvalidHeader, TransferEncodingError)
74+ ):
75+ raise
76
77 if eof:
78 start_pos = 0
79@@ -635,7 +642,7 @@ class HttpRequestParser(HttpParser[RawRequestMessage]):
80 compression,
81 upgrade,
82 chunked,
83- ) = self.parse_headers(lines)
84+ ) = self.parse_headers(lines[1:])
85
86 if close is None: # then the headers weren't set in the request
87 if version_o <= HttpVersion10: # HTTP 1.0 must asks to not close
88@@ -721,7 +728,7 @@ class HttpResponseParser(HttpParser[RawResponseMessage]):
89 compression,
90 upgrade,
91 chunked,
92- ) = self.parse_headers(lines)
93+ ) = self.parse_headers(lines[1:])
94
95 if close is None:
96 if version_o <= HttpVersion10:
97@@ -764,6 +771,8 @@ class HttpPayloadParser:
98 response_with_body: bool = True,
99 auto_decompress: bool = True,
100 lax: bool = False,
101+ *,
102+ headers_parser: HeadersParser,
103 ) -> None:
104 self._length = 0
105 self._type = ParseState.PARSE_UNTIL_EOF
106@@ -772,6 +781,8 @@ class HttpPayloadParser:
107 self._chunk_tail = b""
108 self._auto_decompress = auto_decompress
109 self._lax = lax
110+ self._headers_parser = headers_parser
111+ self._trailer_lines: list[bytes] = []
112 self.done = False
113
114 # payload decompression wrapper
115@@ -848,7 +859,7 @@ class HttpPayloadParser:
116 size_b = chunk[:i] # strip chunk-extensions
117 # Verify no LF in the chunk-extension
118 if b"\n" in (ext := chunk[i:pos]):
119- exc = BadHttpMessage(
120+ exc = TransferEncodingError(
121 f"Unexpected LF in chunk-extension: {ext!r}"
122 )
123 set_exception(self.payload, exc)
124@@ -869,7 +880,7 @@ class HttpPayloadParser:
125
126 chunk = chunk[pos + len(SEP) :]
127 if size == 0: # eof marker
128- self._chunk = ChunkState.PARSE_MAYBE_TRAILERS
129+ self._chunk = ChunkState.PARSE_TRAILERS
130 if self._lax and chunk.startswith(b"\r"):
131 chunk = chunk[1:]
132 else:
133@@ -907,38 +918,31 @@ class HttpPayloadParser:
134 self._chunk_tail = chunk
135 return False, b""
136
137- # if stream does not contain trailer, after 0\r\n
138- # we should get another \r\n otherwise
139- # trailers needs to be skipped until \r\n\r\n
140- if self._chunk == ChunkState.PARSE_MAYBE_TRAILERS:
141- head = chunk[: len(SEP)]
142- if head == SEP:
143- # end of stream
144- self.payload.feed_eof()
145- return True, chunk[len(SEP) :]
146- # Both CR and LF, or only LF may not be received yet. It is
147- # expected that CRLF or LF will be shown at the very first
148- # byte next time, otherwise trailers should come. The last
149- # CRLF which marks the end of response might not be
150- # contained in the same TCP segment which delivered the
151- # size indicator.
152- if not head:
153- return False, b""
154- if head == SEP[:1]:
155- self._chunk_tail = head
156- return False, b""
157- self._chunk = ChunkState.PARSE_TRAILERS
158-
159- # read and discard trailer up to the CRLF terminator
160 if self._chunk == ChunkState.PARSE_TRAILERS:
161 pos = chunk.find(SEP)
162- if pos >= 0:
163- chunk = chunk[pos + len(SEP) :]
164- self._chunk = ChunkState.PARSE_MAYBE_TRAILERS
165- else:
166+ if pos < 0: # No line found
167 self._chunk_tail = chunk
168 return False, b""
169
170+ line = chunk[:pos]
171+ chunk = chunk[pos + len(SEP) :]
172+ if SEP == b"\n": # For lax response parsing
173+ line = line.rstrip(b"\r")
174+ self._trailer_lines.append(line)
175+
176+ # \r\n\r\n found, end of stream
177+ if self._trailer_lines[-1] == b"":
178+ # Headers and trailers are defined the same way,
179+ # so we reuse the HeadersParser here.
180+ try:
181+ trailers, raw_trailers = self._headers_parser.parse_headers(
182+ self._trailer_lines
183+ )
184+ finally:
185+ self._trailer_lines.clear()
186+ self.payload.feed_eof()
187+ return True, chunk
188+
189 # Read all bytes until eof
190 elif self._type == ParseState.PARSE_UNTIL_EOF:
191 self.payload.feed_data(chunk, len(chunk))
192diff --git a/aiohttp/multipart.py b/aiohttp/multipart.py
193index bd4d8ae1d..6faff0e9f 100644
194--- a/aiohttp/multipart.py
195+++ b/aiohttp/multipart.py
196@@ -767,7 +767,7 @@ class MultipartReader:
197 raise ValueError(f"Invalid boundary {chunk!r}, expected {self._boundary!r}")
198
199 async def _read_headers(self) -> "CIMultiDictProxy[str]":
200- lines = [b""]
201+ lines = []
202 while True:
203 chunk = await self._content.readline()
204 chunk = chunk.strip()
205diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py
206index 58fef625f..385452c1c 100644
207--- a/tests/test_http_parser.py
208+++ b/tests/test_http_parser.py
209@@ -17,6 +17,7 @@ from aiohttp.base_protocol import BaseProtocol
210 from aiohttp.http_parser import (
211 NO_EXTENSIONS,
212 DeflateBuffer,
213+ HeadersParser,
214 HttpPayloadParser,
215 HttpRequestParser,
216 HttpRequestParserPy,
217@@ -244,41 +245,13 @@ def test_content_length_transfer_encoding(parser: Any) -> None:
218 parser.feed_data(text)
219
220
221-def test_bad_chunked_py(loop: Any, protocol: Any) -> None:
222+def test_bad_chunked(parser: HttpRequestParser) -> None:
223 """Test that invalid chunked encoding doesn't allow content-length to be used."""
224- parser = HttpRequestParserPy(
225- protocol,
226- loop,
227- 2**16,
228- max_line_size=8190,
229- max_field_size=8190,
230- )
231- text = (
232- b"GET / HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: chunked\r\n\r\n0_2e\r\n\r\n"
233- + b"GET / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n0\r\n\r\n"
234- )
235- messages, upgrade, tail = parser.feed_data(text)
236- assert isinstance(messages[0][1].exception(), http_exceptions.TransferEncodingError)
237-
238-
239-@pytest.mark.skipif(
240- "HttpRequestParserC" not in dir(aiohttp.http_parser),
241- reason="C based HTTP parser not available",
242-)
243-def test_bad_chunked_c(loop: Any, protocol: Any) -> None:
244- """C parser behaves differently. Maybe we should align them later."""
245- parser = HttpRequestParserC(
246- protocol,
247- loop,
248- 2**16,
249- max_line_size=8190,
250- max_field_size=8190,
251- )
252 text = (
253 b"GET / HTTP/1.1\r\nHost: a\r\nTransfer-Encoding: chunked\r\n\r\n0_2e\r\n\r\n"
254 + b"GET / HTTP/1.1\r\nHost: a\r\nContent-Length: 5\r\n\r\n0\r\n\r\n"
255 )
256- with pytest.raises(http_exceptions.BadHttpMessage):
257+ with pytest.raises(http_exceptions.BadHttpMessage, match="0_2e"):
258 parser.feed_data(text)
259
260
261@@ -1158,8 +1131,8 @@ async def test_http_response_parser_bad_chunked_strict_py(loop, protocol) -> Non
262 text = (
263 b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5 \r\nabcde\r\n0\r\n\r\n"
264 )
265- messages, upgrade, tail = response.feed_data(text)
266- assert isinstance(messages[0][1].exception(), http_exceptions.TransferEncodingError)
267+ with pytest.raises(http_exceptions.TransferEncodingError, match="5"):
268+ response.feed_data(text)
269
270
271 @pytest.mark.dev_mode
272@@ -1295,7 +1268,27 @@ def test_parse_chunked_payload_chunk_extension(parser) -> None:
273 assert payload.is_eof()
274
275
276-def test_parse_no_length_or_te_on_post(loop: Any, protocol: Any, request_cls: Any):
277+async def test_request_chunked_with_trailer(parser: HttpRequestParser) -> None:
278+ text = b"GET /test HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n4\r\ntest\r\n0\r\ntest: trailer\r\nsecond: test trailer\r\n\r\n"
279+ messages, upgraded, tail = parser.feed_data(text)
280+ assert not tail
281+ msg, payload = messages[0]
282+ assert await payload.read() == b"test"
283+
284+ # TODO: Add assertion of trailers when API added.
285+
286+
287+async def test_request_chunked_reject_bad_trailer(parser: HttpRequestParser) -> None:
288+ text = b"GET /test HTTP/1.1\r\nTransfer-Encoding: chunked\r\n\r\n0\r\nbad\ntrailer\r\n\r\n"
289+ with pytest.raises(http_exceptions.BadHttpMessage, match=r"b'bad\\ntrailer'"):
290+ parser.feed_data(text)
291+
292+
293+def test_parse_no_length_or_te_on_post(
294+ loop: asyncio.AbstractEventLoop,
295+ protocol: BaseProtocol,
296+ request_cls: type[HttpRequestParser],
297+) -> None:
298 parser = request_cls(protocol, loop, limit=2**16)
299 text = b"POST /test HTTP/1.1\r\n\r\n"
300 msg, payload = parser.feed_data(text)[0][0]
301@@ -1478,19 +1471,10 @@ async def test_parse_chunked_payload_split_chunks(response: Any) -> None:
302 assert await reader.read() == b"firstsecond"
303
304
305-@pytest.mark.skipif(NO_EXTENSIONS, reason="Only tests C parser.")
306-async def test_parse_chunked_payload_with_lf_in_extensions_c_parser(
307- loop: asyncio.AbstractEventLoop, protocol: BaseProtocol
308+async def test_parse_chunked_payload_with_lf_in_extensions(
309+ parser: HttpRequestParser,
310 ) -> None:
311- """Test the C-parser with a chunked payload that has a LF in the chunk extensions."""
312- # The C parser will raise a BadHttpMessage from feed_data
313- parser = HttpRequestParserC(
314- protocol,
315- loop,
316- 2**16,
317- max_line_size=8190,
318- max_field_size=8190,
319- )
320+ """Test chunked payload that has a LF in the chunk extensions."""
321 payload = (
322 b"GET / HTTP/1.1\r\nHost: localhost:5001\r\n"
323 b"Transfer-Encoding: chunked\r\n\r\n2;\nxx\r\n4c\r\n0\r\n\r\n"
324@@ -1501,31 +1485,6 @@ async def test_parse_chunked_payload_with_lf_in_extensions_c_parser(
325 parser.feed_data(payload)
326
327
328-async def test_parse_chunked_payload_with_lf_in_extensions_py_parser(
329- loop: asyncio.AbstractEventLoop, protocol: BaseProtocol
330-) -> None:
331- """Test the py-parser with a chunked payload that has a LF in the chunk extensions."""
332- # The py parser will not raise the BadHttpMessage directly, but instead
333- # it will set the exception on the StreamReader.
334- parser = HttpRequestParserPy(
335- protocol,
336- loop,
337- 2**16,
338- max_line_size=8190,
339- max_field_size=8190,
340- )
341- payload = (
342- b"GET / HTTP/1.1\r\nHost: localhost:5001\r\n"
343- b"Transfer-Encoding: chunked\r\n\r\n2;\nxx\r\n4c\r\n0\r\n\r\n"
344- b"GET /admin HTTP/1.1\r\nHost: localhost:5001\r\n"
345- b"Transfer-Encoding: chunked\r\n\r\n0\r\n\r\n"
346- )
347- messages, _, _ = parser.feed_data(payload)
348- reader = messages[0][1]
349- assert isinstance(reader.exception(), http_exceptions.BadHttpMessage)
350- assert "\\nxx" in str(reader.exception())
351-
352-
353 def test_partial_url(parser: HttpRequestParser) -> None:
354 messages, upgrade, tail = parser.feed_data(b"GET /te")
355 assert len(messages) == 0
356@@ -1612,7 +1571,7 @@ def test_parse_bad_method_for_c_parser_raises(loop, protocol):
357 class TestParsePayload:
358 async def test_parse_eof_payload(self, protocol: BaseProtocol) -> None:
359 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
360- p = HttpPayloadParser(out)
361+ p = HttpPayloadParser(out, headers_parser=HeadersParser())
362 p.feed_data(b"data")
363 p.feed_eof()
364
365@@ -1622,7 +1581,7 @@ class TestParsePayload:
366 async def test_parse_length_payload_eof(self, protocol: BaseProtocol) -> None:
367 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
368
369- p = HttpPayloadParser(out, length=4)
370+ p = HttpPayloadParser(out, length=4, headers_parser=HeadersParser())
371 p.feed_data(b"da")
372
373 with pytest.raises(http_exceptions.ContentLengthError):
374@@ -1632,7 +1591,7 @@ class TestParsePayload:
375 self, protocol: BaseProtocol
376 ) -> None:
377 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
378- p = HttpPayloadParser(out, chunked=True)
379+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
380 with pytest.raises(http_exceptions.TransferEncodingError):
381 p.feed_data(b"blah\r\n")
382 assert isinstance(out.exception(), http_exceptions.TransferEncodingError)
383@@ -1641,7 +1600,7 @@ class TestParsePayload:
384 self, protocol: BaseProtocol
385 ) -> None:
386 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
387- p = HttpPayloadParser(out, chunked=True)
388+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
389 p.feed_data(b"4\r\nasdf\r\n0\r\n")
390 p.feed_data(b"\r\n")
391
392@@ -1652,7 +1611,7 @@ class TestParsePayload:
393 self, protocol: BaseProtocol
394 ) -> None:
395 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
396- p = HttpPayloadParser(out, chunked=True)
397+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
398 p.feed_data(b"4\r\nasdf\r\n0\r\n\r")
399 p.feed_data(b"\n")
400
401@@ -1663,7 +1622,7 @@ class TestParsePayload:
402 self, protocol: BaseProtocol
403 ) -> None:
404 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
405- p = HttpPayloadParser(out, chunked=True)
406+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
407 p.feed_data(b"4\r\nasdf\r\n0\r\n")
408 p.feed_data(b"Content-MD5: 912ec803b2ce49e4a541068d495ab570\r\n")
409 p.feed_data(b"\r\n")
410@@ -1675,7 +1634,7 @@ class TestParsePayload:
411 self, protocol: BaseProtocol
412 ) -> None:
413 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
414- p = HttpPayloadParser(out, chunked=True)
415+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
416 p.feed_data(b"4\r\nasdf\r\n0\r\n")
417 p.feed_data(b"Content-MD5: 912ec803b2ce49e4a541068d495ab570\r\n\r")
418 p.feed_data(b"\n")
419@@ -1687,7 +1646,7 @@ class TestParsePayload:
420 self, protocol: BaseProtocol
421 ) -> None:
422 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
423- p = HttpPayloadParser(out, chunked=True)
424+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
425 p.feed_data(b"4\r\nasdf\r\n0\r\nContent-MD5: ")
426 p.feed_data(b"912ec803b2ce49e4a541068d495ab570\r\n\r\n")
427
428@@ -1698,7 +1657,7 @@ class TestParsePayload:
429 self, protocol: BaseProtocol
430 ) -> None:
431 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
432- p = HttpPayloadParser(out, chunked=True)
433+ p = HttpPayloadParser(out, chunked=True, headers_parser=HeadersParser())
434 p.feed_data(b"4\r\nasdf\r\n0\r\nC")
435 p.feed_data(b"ontent-MD5: 912ec803b2ce49e4a541068d495ab570\r\n\r\n")
436
437@@ -1707,7 +1666,7 @@ class TestParsePayload:
438
439 async def test_http_payload_parser_length(self, protocol: BaseProtocol) -> None:
440 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
441- p = HttpPayloadParser(out, length=2)
442+ p = HttpPayloadParser(out, length=2, headers_parser=HeadersParser())
443 eof, tail = p.feed_data(b"1245")
444 assert eof
445
446@@ -1720,7 +1679,9 @@ class TestParsePayload:
447
448 length = len(COMPRESSED)
449 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
450- p = HttpPayloadParser(out, length=length, compression="deflate")
451+ p = HttpPayloadParser(
452+ out, length=length, compression="deflate", headers_parser=HeadersParser()
453+ )
454 p.feed_data(COMPRESSED)
455 assert b"data" == out._buffer[0]
456 assert out.is_eof()
457@@ -1734,7 +1695,9 @@ class TestParsePayload:
458
459 length = len(COMPRESSED)
460 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
461- p = HttpPayloadParser(out, length=length, compression="deflate")
462+ p = HttpPayloadParser(
463+ out, length=length, compression="deflate", headers_parser=HeadersParser()
464+ )
465 p.feed_data(COMPRESSED)
466 assert b"data" == out._buffer[0]
467 assert out.is_eof()
468@@ -1747,7 +1710,9 @@ class TestParsePayload:
469
470 length = len(COMPRESSED)
471 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
472- p = HttpPayloadParser(out, length=length, compression="deflate")
473+ p = HttpPayloadParser(
474+ out, length=length, compression="deflate", headers_parser=HeadersParser()
475+ )
476 p.feed_data(COMPRESSED)
477
478 assert b"data" == out._buffer[0]
479@@ -1757,7 +1722,9 @@ class TestParsePayload:
480 self, protocol: BaseProtocol
481 ) -> None:
482 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
483- p = HttpPayloadParser(out, compression="deflate")
484+ p = HttpPayloadParser(
485+ out, compression="deflate", headers_parser=HeadersParser()
486+ )
487 # Feeding one correct byte should be enough to choose exact
488 # deflate decompressor
489 p.feed_data(b"x")
490@@ -1769,7 +1736,9 @@ class TestParsePayload:
491 self, protocol: BaseProtocol
492 ) -> None:
493 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
494- p = HttpPayloadParser(out, compression="deflate")
495+ p = HttpPayloadParser(
496+ out, compression="deflate", headers_parser=HeadersParser()
497+ )
498 # Feeding one wrong byte should be enough to choose exact
499 # deflate decompressor
500 p.feed_data(b"K")
501@@ -1781,7 +1750,7 @@ class TestParsePayload:
502 self, protocol: BaseProtocol
503 ) -> None:
504 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
505- p = HttpPayloadParser(out, length=0)
506+ p = HttpPayloadParser(out, length=0, headers_parser=HeadersParser())
507 assert p.done
508 assert out.is_eof()
509
510@@ -1789,7 +1758,12 @@ class TestParsePayload:
511 async def test_http_payload_brotli(self, protocol: BaseProtocol) -> None:
512 compressed = brotli.compress(b"brotli data")
513 out = aiohttp.StreamReader(protocol, 2**16, loop=asyncio.get_running_loop())
514- p = HttpPayloadParser(out, length=len(compressed), compression="br")
515+ p = HttpPayloadParser(
516+ out,
517+ length=len(compressed),
518+ compression="br",
519+ headers_parser=HeadersParser(),
520+ )
521 p.feed_data(compressed)
522 assert b"brotli data" == out._buffer[0]
523 assert out.is_eof()
524--
5252.34.1
526