python-aiohttp/CVE-2023-47641.patch
starlet-dx e71a01ad20 Fix CVE-2023-47641
(cherry picked from commit 3d08826106fbc642e764659443bda0069b14e19c)
2023-11-16 14:38:41 +08:00

78 lines
2.6 KiB
Diff

From f016f0680e4ace6742b03a70cb0382ce86abe371 Mon Sep 17 00:00:00 2001
From: Andrew Svetlov <andrew.svetlov@gmail.com>
Date: Sun, 31 Oct 2021 19:03:06 +0200
Subject: [PATCH] Raise '400: Content-Length can't be present with
Transfer-Encoding' if both Content-Length and Transfer-Encoding are sent by
peer (#6182)
---
CHANGES/6182.bugfix | 1 +
aiohttp/http_parser.py | 12 ++++++++++--
tests/test_http_parser.py | 15 ++++++++++++++-
3 files changed, 25 insertions(+), 3 deletions(-)
create mode 100644 CHANGES/6182.bugfix
diff --git a/CHANGES/6182.bugfix b/CHANGES/6182.bugfix
new file mode 100644
index 0000000000..28daaa328a
--- /dev/null
+++ b/CHANGES/6182.bugfix
@@ -0,0 +1 @@
+Raise ``400: Content-Length can't be present with Transfer-Encoding`` if both ``Content-Length`` and ``Transfer-Encoding`` are sent by peer by both C and Python implementations
diff --git a/aiohttp/http_parser.py b/aiohttp/http_parser.py
index 4a4ae31ae6..e1b86e8e4f 100644
--- a/aiohttp/http_parser.py
+++ b/aiohttp/http_parser.py
@@ -28,6 +28,7 @@
from .base_protocol import BaseProtocol
from .helpers import NO_EXTENSIONS, BaseTimerContext
from .http_exceptions import (
+ BadHttpMessage,
BadStatusLine,
ContentEncodingError,
ContentLengthError,
@@ -489,8 +490,15 @@ def parse_headers(
# chunking
te = headers.get(hdrs.TRANSFER_ENCODING)
- if te and "chunked" in te.lower():
- chunked = True
+ if te is not None:
+ te_lower = te.lower()
+ if "chunked" in te_lower:
+ chunked = True
+
+ if hdrs.CONTENT_LENGTH in headers:
+ raise BadHttpMessage(
+ "Content-Length can't be present with Transfer-Encoding",
+ )
return (headers, raw_headers, close_conn, encoding, upgrade, chunked)
diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py
index 78e9ea6401..d86d238f58 100644
--- a/tests/test_http_parser.py
+++ b/tests/test_http_parser.py
@@ -291,7 +291,20 @@ def test_request_chunked(parser) -> None:
assert isinstance(payload, streams.StreamReader)
-def test_conn_upgrade(parser) -> None:
+def test_request_te_chunked_with_content_length(parser: Any) -> None:
+ text = (
+ b"GET /test HTTP/1.1\r\n"
+ b"content-length: 1234\r\n"
+ b"transfer-encoding: chunked\r\n\r\n"
+ )
+ with pytest.raises(
+ http_exceptions.BadHttpMessage,
+ match="Content-Length can't be present with Transfer-Encoding",
+ ):
+ parser.feed_data(text)
+
+
+def test_conn_upgrade(parser: Any) -> None:
text = (
b"GET /test HTTP/1.1\r\n"
b"connection: upgrade\r\n"