Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-python-multipart for 
openSUSE:Factory checked in at 2024-12-05 17:05:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-python-multipart (Old)
 and      /work/SRC/openSUSE:Factory/.python-python-multipart.new.28523 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-python-multipart"

Thu Dec  5 17:05:16 2024 rev:10 rq:1228255 version:0.0.19

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-python-multipart/python-python-multipart.changes
  2024-11-08 11:58:40.971718077 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-python-multipart.new.28523/python-python-multipart.changes
       2024-12-05 17:05:44.566311739 +0100
@@ -1,0 +2,8 @@
+Wed Dec  4 10:08:03 UTC 2024 - Daniel Garcia <[email protected]>
+
+- Update to 0.0.19 (bsc#1234115, CVE-2024-53981):
+  * Don't warn when CRLF is found after last boundary #193
+- 0.0.18:
+  * Hard break if found data after last boundary on MultipartParser #189
+
+-------------------------------------------------------------------

Old:
----
  python_multipart-0.0.17.tar.gz

New:
----
  python_multipart-0.0.19.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-python-multipart.spec ++++++
--- /var/tmp/diff_new_pack.uybWe6/_old  2024-12-05 17:05:45.218339044 +0100
+++ /var/tmp/diff_new_pack.uybWe6/_new  2024-12-05 17:05:45.218339044 +0100
@@ -18,11 +18,11 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-python-multipart
-Version:        0.0.17
+Version:        0.0.19
 Release:        0
 License:        Apache-2.0
 Summary:        Python streaming multipart parser
-URL:            http://github.com/andrew-d/python-multipart
+URL:            http://github.com/Kludex/python-multipart
 Source:         
https://files.pythonhosted.org/packages/source/p/python-multipart/python_multipart-%{version}.tar.gz
 BuildRequires:  %{python_module hatchling}
 BuildRequires:  %{python_module pip}

++++++ python_multipart-0.0.17.tar.gz -> python_multipart-0.0.19.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python_multipart-0.0.17/CHANGELOG.md 
new/python_multipart-0.0.19/CHANGELOG.md
--- old/python_multipart-0.0.17/CHANGELOG.md    2020-02-02 01:00:00.000000000 
+0100
+++ new/python_multipart-0.0.19/CHANGELOG.md    2020-02-02 01:00:00.000000000 
+0100
@@ -1,5 +1,13 @@
 # Changelog
 
+## 0.0.19 (2024-11-30)
+
+* Don't warn when CRLF is found after last boundary on `MultipartParser` 
[#193](https://github.com/Kludex/python-multipart/pull/193).
+
+## 0.0.18 (2024-11-28)
+
+* Hard break if found data after last boundary on `MultipartParser` 
[#189](https://github.com/Kludex/python-multipart/pull/189).
+
 ## 0.0.17 (2024-10-31)
 
 * Handle PermissionError in fallback code for old import name 
[#182](https://github.com/Kludex/python-multipart/pull/182).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python_multipart-0.0.17/PKG-INFO 
new/python_multipart-0.0.19/PKG-INFO
--- old/python_multipart-0.0.17/PKG-INFO        2020-02-02 01:00:00.000000000 
+0100
+++ new/python_multipart-0.0.19/PKG-INFO        2020-02-02 01:00:00.000000000 
+0100
@@ -1,14 +1,13 @@
 Metadata-Version: 2.3
 Name: python-multipart
-Version: 0.0.17
+Version: 0.0.19
 Summary: A streaming multipart parser for Python
 Project-URL: Homepage, https://github.com/Kludex/python-multipart
 Project-URL: Documentation, https://kludex.github.io/python-multipart/
 Project-URL: Changelog, 
https://github.com/Kludex/python-multipart/blob/master/CHANGELOG.md
 Project-URL: Source, https://github.com/Kludex/python-multipart
 Author-email: Andrew Dunham <[email protected]>, Marcelo Trylesinski 
<[email protected]>
-License-Expression: Apache-2.0
-License-File: LICENSE.txt
+License: Apache-2.0
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Web Environment
 Classifier: Intended Audience :: Developers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python_multipart-0.0.17/pyproject.toml 
new/python_multipart-0.0.19/pyproject.toml
--- old/python_multipart-0.0.17/pyproject.toml  2020-02-02 01:00:00.000000000 
+0100
+++ new/python_multipart-0.0.19/pyproject.toml  2020-02-02 01:00:00.000000000 
+0100
@@ -44,7 +44,7 @@
     "PyYAML==6.0.1",
     "invoke==2.2.0",
     "pytest-timeout==2.3.1",
-    "ruff==0.3.4",
+    "ruff==0.8.0",
     "mypy",
     "types-PyYAML",
     "atheris==2.3.0; python_version != '3.12'",
@@ -122,4 +122,4 @@
 ]
 
 [tool.check-sdist]
-git-only = ["docs", "fuzz", "scripts", "mkdocs.yml", "uv.lock"]
+git-only = ["docs", "fuzz", "scripts", "mkdocs.yml", "uv.lock", "SECURITY.md"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python_multipart-0.0.17/python_multipart/__init__.py 
new/python_multipart-0.0.19/python_multipart/__init__.py
--- old/python_multipart-0.0.17/python_multipart/__init__.py    2020-02-02 
01:00:00.000000000 +0100
+++ new/python_multipart-0.0.19/python_multipart/__init__.py    2020-02-02 
01:00:00.000000000 +0100
@@ -2,7 +2,7 @@
 __author__ = "Andrew Dunham"
 __license__ = "Apache"
 __copyright__ = "Copyright (c) 2012-2013, Andrew Dunham"
-__version__ = "0.0.17"
+__version__ = "0.0.19"
 
 from .multipart import (
     BaseParser,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python_multipart-0.0.17/python_multipart/multipart.py 
new/python_multipart-0.0.19/python_multipart/multipart.py
--- old/python_multipart-0.0.17/python_multipart/multipart.py   2020-02-02 
01:00:00.000000000 +0100
+++ new/python_multipart-0.0.19/python_multipart/multipart.py   2020-02-02 
01:00:00.000000000 +0100
@@ -1105,7 +1105,6 @@
                 # Skip leading newlines
                 if c == CR or c == LF:
                     i += 1
-                    self.logger.debug("Skipping leading CR/LF at %d", i)
                     continue
 
                 # index is used as in index into our boundary.  Set to 0.
@@ -1398,9 +1397,14 @@
                     i -= 1
 
             elif state == MultipartState.END:
-                # Do nothing and just consume a byte in the end state.
-                if c not in (CR, LF):
-                    self.logger.warning("Consuming a byte '0x%x' in the end 
state", c)  # pragma: no cover
+                # Don't do anything if chunk ends with CRLF.
+                if c == CR and i + 1 < length and data[i + 1] == LF:
+                    i += 2
+                    continue
+                # Skip data after the last boundary.
+                self.logger.warning("Skipping data after last boundary")
+                i = length
+                break
 
             else:  # pragma: no cover (error case)
                 # We got into a strange state somehow!  Just stop processing.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python_multipart-0.0.17/tests/test_multipart.py 
new/python_multipart-0.0.19/tests/test_multipart.py
--- old/python_multipart-0.0.17/tests/test_multipart.py 2020-02-02 
01:00:00.000000000 +0100
+++ new/python_multipart-0.0.19/tests/test_multipart.py 2020-02-02 
01:00:00.000000000 +0100
@@ -1,5 +1,6 @@
 from __future__ import annotations
 
+import logging
 import os
 import random
 import sys
@@ -9,6 +10,7 @@
 from typing import TYPE_CHECKING, cast
 from unittest.mock import Mock
 
+import pytest
 import yaml
 
 from python_multipart.decoders import Base64Decoder, QuotedPrintableDecoder
@@ -825,7 +827,7 @@
             return
 
         # No error!
-        self.assertEqual(processed, len(param["test"]))
+        self.assertEqual(processed, len(param["test"]), param["name"])
 
         # Assert that the parser gave us the appropriate fields/files.
         for e in param["result"]["expected"]:
@@ -1210,6 +1212,68 @@
         self.assertEqual(fields[2].field_name, b"baz")
         self.assertEqual(fields[2].value, b"asdf")
 
+    def test_multipart_parser_newlines_before_first_boundary(self) -> None:
+        """This test makes sure that the parser does not handle when there is 
junk data after the last boundary."""
+        num = 5_000_000
+        data = (
+            "\r\n" * num + "--boundary\r\n"
+            'Content-Disposition: form-data; name="file"; 
filename="filename.txt"\r\n'
+            "Content-Type: text/plain\r\n\r\n"
+            "hello\r\n"
+            "--boundary--"
+        )
+
+        files: list[File] = []
+
+        def on_file(f: FileProtocol) -> None:
+            files.append(cast(File, f))
+
+        f = FormParser("multipart/form-data", on_field=Mock(), 
on_file=on_file, boundary="boundary")
+        f.write(data.encode("latin-1"))
+
+    def test_multipart_parser_data_after_last_boundary(self) -> None:
+        """This test makes sure that the parser does not handle when there is 
junk data after the last boundary."""
+        num = 50_000_000
+        data = (
+            "--boundary\r\n"
+            'Content-Disposition: form-data; name="file"; 
filename="filename.txt"\r\n'
+            "Content-Type: text/plain\r\n\r\n"
+            "hello\r\n"
+            "--boundary--" + "-" * num + "\r\n"
+        )
+
+        files: list[File] = []
+
+        def on_file(f: FileProtocol) -> None:
+            files.append(cast(File, f))
+
+        f = FormParser("multipart/form-data", on_field=Mock(), 
on_file=on_file, boundary="boundary")
+        f.write(data.encode("latin-1"))
+
+    @pytest.fixture(autouse=True)
+    def inject_fixtures(self, caplog: pytest.LogCaptureFixture) -> None:
+        self._caplog = caplog
+
+    def test_multipart_parser_data_end_with_crlf_without_warnings(self) -> 
None:
+        """This test makes sure that the parser does not handle when the data 
ends with a CRLF."""
+        data = (
+            "--boundary\r\n"
+            'Content-Disposition: form-data; name="file"; 
filename="filename.txt"\r\n'
+            "Content-Type: text/plain\r\n\r\n"
+            "hello\r\n"
+            "--boundary--\r\n"
+        )
+
+        files: list[File] = []
+
+        def on_file(f: FileProtocol) -> None:
+            files.append(cast(File, f))
+
+        f = FormParser("multipart/form-data", on_field=Mock(), 
on_file=on_file, boundary="boundary")
+        with self._caplog.at_level(logging.WARNING):
+            f.write(data.encode("latin-1"))
+            assert len(self._caplog.records) == 0
+
     def test_max_size_multipart(self) -> None:
         # Load test data.
         test_file = "single_field_single_file.http"

Reply via email to