92 lines
3.5 KiB
Diff
92 lines
3.5 KiB
Diff
Index: aiohttp-3.8.5/CHANGES/9851.bugfix.rst
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ aiohttp-3.8.5/CHANGES/9851.bugfix.rst
|
|
@@ -0,0 +1 @@
|
|
+Fixed incorrect parsing of chunk extensions with the pure Python parser -- by :user:`bdraco`.
|
|
Index: aiohttp-3.8.5/aiohttp/http_parser.py
|
|
===================================================================
|
|
--- aiohttp-3.8.5.orig/aiohttp/http_parser.py
|
|
+++ aiohttp-3.8.5/aiohttp/http_parser.py
|
|
@@ -26,7 +26,7 @@ from yarl import URL
|
|
|
|
from . import hdrs
|
|
from .base_protocol import BaseProtocol
|
|
-from .helpers import NO_EXTENSIONS, BaseTimerContext
|
|
+from .helpers import NO_EXTENSIONS, BaseTimerContext, set_exception
|
|
from .http_exceptions import (
|
|
BadHttpMessage,
|
|
BadStatusLine,
|
|
@@ -770,6 +770,14 @@ class HttpPayloadParser:
|
|
i = chunk.find(CHUNK_EXT, 0, pos)
|
|
if i >= 0:
|
|
size_b = chunk[:i] # strip chunk-extensions
|
|
+ # Verify no LF in the chunk-extension
|
|
+ if b"\n" in chunk[i:pos]:
|
|
+ ext = repr(chunk[i:pos])
|
|
+ exc = BadHttpMessage(
|
|
+ "Unexpected LF in chunk-extension: %s" % ext
|
|
+ )
|
|
+ set_exception(self.payload, exc)
|
|
+ raise exc
|
|
else:
|
|
size_b = chunk[:pos]
|
|
|
|
Index: aiohttp-3.8.5/tests/test_http_parser.py
|
|
===================================================================
|
|
--- aiohttp-3.8.5.orig/tests/test_http_parser.py
|
|
+++ aiohttp-3.8.5/tests/test_http_parser.py
|
|
@@ -12,6 +12,7 @@ from yarl import URL
|
|
|
|
import aiohttp
|
|
from aiohttp import http_exceptions, streams
|
|
+from aiohttp.base_protocol import BaseProtocol
|
|
from aiohttp.http_parser import (
|
|
NO_EXTENSIONS,
|
|
DeflateBuffer,
|
|
@@ -1202,3 +1203,27 @@ class TestDeflateBuffer:
|
|
dbuf.feed_eof()
|
|
|
|
assert buf.at_eof()
|
|
+
|
|
+
|
|
+async def test_parse_chunked_payload_with_lf_in_extensions_py_parser(
|
|
+ loop: asyncio.AbstractEventLoop, protocol: BaseProtocol
|
|
+) -> None:
|
|
+ """Test the py-parser with a chunked payload that has a LF in the chunk extensions."""
|
|
+ # The py parser will not raise the BadHttpMessage directly, but instead
|
|
+ # it will set the exception on the StreamReader.
|
|
+ parser = HttpRequestParserPy(
|
|
+ protocol,
|
|
+ loop,
|
|
+ max_line_size=8190,
|
|
+ max_field_size=8190,
|
|
+ )
|
|
+ payload = (
|
|
+ b"GET / HTTP/1.1\r\nHost: localhost:5001\r\n"
|
|
+ b"Transfer-Encoding: chunked\r\n\r\n2;\nxx\r\n4c\r\n0\r\n\r\n"
|
|
+ b"GET /admin HTTP/1.1\r\nHost: localhost:5001\r\n"
|
|
+ b"Transfer-Encoding: chunked\r\n\r\n0\r\n\r\n"
|
|
+ )
|
|
+ messages, _, _ = parser.feed_data(payload)
|
|
+ reader = messages[0][1]
|
|
+ assert isinstance(reader.exception(), http_exceptions.BadHttpMessage)
|
|
+ assert "\\nxx" in str(reader.exception())
|
|
Index: aiohttp-3.8.5/aiohttp/helpers.py
|
|
===================================================================
|
|
--- aiohttp-3.8.5.orig/aiohttp/helpers.py
|
|
+++ aiohttp-3.8.5/aiohttp/helpers.py
|
|
@@ -796,8 +796,10 @@ def set_result(fut: "asyncio.Future[_T]"
|
|
|
|
|
|
def set_exception(fut: "asyncio.Future[_T]", exc: BaseException) -> None:
|
|
- if not fut.done():
|
|
- fut.set_exception(exc)
|
|
+ if asyncio.isfuture(fut) and fut.done():
|
|
+ return
|
|
+
|
|
+ fut.set_exception(exc)
|
|
|
|
|
|
class ChainMapProxy(Mapping[str, Any]):
|