File CVE-2024-49767.patch of Package python-Werkzeug.36256

Index: Werkzeug-2.3.6/CHANGES.rst
===================================================================
--- Werkzeug-2.3.6.orig/CHANGES.rst
+++ Werkzeug-2.3.6/CHANGES.rst
@@ -8,6 +8,9 @@ Released 2023-06-08
 -   ``FileStorage.content_length`` does not fail if the form data did not provide a
     value. :issue:`2726`
 
+-   Fix how ``max_form_memory_size`` is applied when parsing large non-file
+    fields. :ghsa:`q34m-jh98-gwm2`
+
 
 Version 2.3.5
 -------------
Index: Werkzeug-2.3.6/src/werkzeug/formparser.py
===================================================================
--- Werkzeug-2.3.6.orig/src/werkzeug/formparser.py
+++ Werkzeug-2.3.6/src/werkzeug/formparser.py
@@ -480,6 +480,7 @@ class MultiPartParser:
         self, stream: t.IO[bytes], boundary: bytes, content_length: int | None
     ) -> tuple[MultiDict, MultiDict]:
         current_part: Field | File
+        field_size: int | None = None
         container: t.IO[bytes] | list[bytes]
         _write: t.Callable[[bytes], t.Any]
 
@@ -498,13 +499,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):
Index: Werkzeug-2.3.6/src/werkzeug/sansio/multipart.py
===================================================================
--- Werkzeug-2.3.6.orig/src/werkzeug/sansio/multipart.py
+++ Werkzeug-2.3.6/src/werkzeug/sansio/multipart.py
@@ -140,6 +140,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)
Index: Werkzeug-2.3.6/tests/test_formparser.py
===================================================================
--- Werkzeug-2.3.6.orig/tests/test_formparser.py
+++ Werkzeug-2.3.6/tests/test_formparser.py
@@ -448,3 +448,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)
openSUSE Build Service is sponsored by