Fix CVE-2024-49767
(cherry picked from commit c7566002c0a7d671ce568caacd3be66f7a70d536)
This commit is contained in:
parent
9700a2e751
commit
f633b8388e
@ -0,0 +1,83 @@
|
|||||||
|
From 8760275afb72bd10b57d92cb4d52abf759b2f3a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Lord <davidism@gmail.com>
|
||||||
|
Date: Fri, 25 Oct 2024 06:46:50 -0700
|
||||||
|
Subject: [PATCH] apply max_form_memory_size another level up in the parser
|
||||||
|
|
||||||
|
---
|
||||||
|
src/werkzeug/formparser.py | 11 +++++++++++
|
||||||
|
src/werkzeug/sansio/multipart.py | 2 ++
|
||||||
|
tests/test_formparser.py | 12 ++++++++++++
|
||||||
|
3 files changed, 25 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/werkzeug/formparser.py b/src/werkzeug/formparser.py
|
||||||
|
index bebb2fc..b82af82 100644
|
||||||
|
--- a/src/werkzeug/formparser.py
|
||||||
|
+++ b/src/werkzeug/formparser.py
|
||||||
|
@@ -405,6 +405,7 @@ class MultiPartParser:
|
||||||
|
def parse(
|
||||||
|
self, stream: t.IO[bytes], boundary: bytes, content_length: t.Optional[int]
|
||||||
|
) -> t.Tuple[MultiDict, MultiDict]:
|
||||||
|
+ field_size: int | None = None
|
||||||
|
container: t.Union[t.IO[bytes], t.List[bytes]]
|
||||||
|
_write: t.Callable[[bytes], t.Any]
|
||||||
|
|
||||||
|
@@ -431,13 +432,23 @@ class MultiPartParser:
|
||||||
|
while not isinstance(event, (Epilogue, NeedData)):
|
||||||
|
if isinstance(event, Field):
|
||||||
|
current_part = event
|
||||||
|
+ field_size = 0
|
||||||
|
container = []
|
||||||
|
_write = container.append
|
||||||
|
elif isinstance(event, File):
|
||||||
|
current_part = event
|
||||||
|
+ field_size = None
|
||||||
|
container = self.start_file_streaming(event, content_length)
|
||||||
|
_write = container.write
|
||||||
|
elif isinstance(event, Data):
|
||||||
|
+ if self.max_form_memory_size is not None and field_size is not None:
|
||||||
|
+ # Ensure that accumulated data events do not exceed limit.
|
||||||
|
+ # Also checked within single event in MultipartDecoder.
|
||||||
|
+ field_size += len(event.data)
|
||||||
|
+
|
||||||
|
+ if field_size > self.max_form_memory_size:
|
||||||
|
+ raise RequestEntityTooLarge()
|
||||||
|
+
|
||||||
|
_write(event.data)
|
||||||
|
if not event.more_data:
|
||||||
|
if isinstance(current_part, Field):
|
||||||
|
diff --git a/src/werkzeug/sansio/multipart.py b/src/werkzeug/sansio/multipart.py
|
||||||
|
index 2684e5d..e2b0e79 100644
|
||||||
|
--- a/src/werkzeug/sansio/multipart.py
|
||||||
|
+++ b/src/werkzeug/sansio/multipart.py
|
||||||
|
@@ -142,6 +142,8 @@ class MultipartDecoder:
|
||||||
|
self.max_form_memory_size is not None
|
||||||
|
and len(self.buffer) + len(data) > self.max_form_memory_size
|
||||||
|
):
|
||||||
|
+ # Ensure that data within single event does not exceed limit.
|
||||||
|
+ # Also checked across accumulated events in MultiPartParser.
|
||||||
|
raise RequestEntityTooLarge()
|
||||||
|
else:
|
||||||
|
self.buffer.extend(data)
|
||||||
|
diff --git a/tests/test_formparser.py b/tests/test_formparser.py
|
||||||
|
index 4c518b1..05fa84e 100644
|
||||||
|
--- a/tests/test_formparser.py
|
||||||
|
+++ b/tests/test_formparser.py
|
||||||
|
@@ -455,3 +455,15 @@ class TestMultiPartParser:
|
||||||
|
) as request:
|
||||||
|
assert request.files["rfc2231"].filename == "a b c d e f.txt"
|
||||||
|
assert request.files["rfc2231"].read() == b"file contents"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def test_multipart_max_form_memory_size() -> None:
|
||||||
|
+ """max_form_memory_size is tracked across multiple data events."""
|
||||||
|
+ data = b"--bound\r\nContent-Disposition: form-field; name=a\r\n\r\n"
|
||||||
|
+ data += b"a" * 15 + b"\r\n--bound--"
|
||||||
|
+ # The buffer size is less than the max size, so multiple data events will be
|
||||||
|
+ # returned. The field size is greater than the max.
|
||||||
|
+ parser = formparser.MultiPartParser(max_form_memory_size=10, buffer_size=5)
|
||||||
|
+
|
||||||
|
+ with pytest.raises(RequestEntityTooLarge):
|
||||||
|
+ parser.parse(io.BytesIO(data), b"bound", None)
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
%global _empty_manifest_terminate_build 0
|
%global _empty_manifest_terminate_build 0
|
||||||
Name: python-werkzeug
|
Name: python-werkzeug
|
||||||
Version: 2.2.3
|
Version: 2.2.3
|
||||||
Release: 2
|
Release: 3
|
||||||
Summary: The comprehensive WSGI web application library.
|
Summary: The comprehensive WSGI web application library.
|
||||||
License: BSD-3-Clause
|
License: BSD-3-Clause
|
||||||
URL: https://palletsprojects.com/p/werkzeug/
|
URL: https://palletsprojects.com/p/werkzeug/
|
||||||
@ -11,6 +11,7 @@ Source1: https://github.com/Yelp/ephemeral-port-reserve/blob/master/ephem
|
|||||||
|
|
||||||
Patch01: CVE-2024-34069-restrict-debugger-trusted-hosts.patch
|
Patch01: CVE-2024-34069-restrict-debugger-trusted-hosts.patch
|
||||||
Patch02: CVE-2024-34069-only-require-trusted-host-for-evalex.patch
|
Patch02: CVE-2024-34069-only-require-trusted-host-for-evalex.patch
|
||||||
|
Patch03: CVE-2024-49767--apply-max_form_memory_size-another-level-up.patch
|
||||||
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
BuildRequires: python3-werkzeug python3-markupsafe
|
BuildRequires: python3-werkzeug python3-markupsafe
|
||||||
@ -174,6 +175,9 @@ PYTHONPATH=%{buildroot}%{python3_sitelib} pytest -k 'not (test_serving)'
|
|||||||
%{_docdir}/*
|
%{_docdir}/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sat Oct 26 2024 liningjie <liningjie@xfusion.com> - 2.2.3-3
|
||||||
|
- Fix CVE-2024-49767
|
||||||
|
|
||||||
* Tue May 07 2024 yinyongkang <yinyongkang@kylinos.cn> - 2.2.3-2
|
* Tue May 07 2024 yinyongkang <yinyongkang@kylinos.cn> - 2.2.3-2
|
||||||
- fix CVE-2024-34069
|
- fix CVE-2024-34069
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user