From 238a27f3fb8e13bc68ff0b445f0aebcc23c8c692 Mon Sep 17 00:00:00 2001 From: manunio Date: Sat, 25 Apr 2026 19:28:06 +0530 Subject: [PATCH 1/4] Fix parse_options_header to handle ValueError and add test for oversized RFC 2231 index --- python_multipart/multipart.py | 5 ++++- tests/test_multipart.py | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index 2435bdc..774b48e 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -171,7 +171,10 @@ def parse_options_header(value: str | bytes | None) -> tuple[bytes, dict[bytes, # ctype, rest = value.split(b';', 1) message = Message() message["content-type"] = value - params = message.get_params() + try: + params = message.get_params() + except ValueError: + return (value.split(";", 1)[0].lower().strip().encode("latin-1"), {}) # If there were no parameters, this would have already returned above assert params, "At least the content type value should be present" ctype = params.pop(0)[0].encode("latin-1") diff --git a/tests/test_multipart.py b/tests/test_multipart.py index fce3253..ed685a3 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -304,6 +304,12 @@ def test_handles_rfc_2231(self) -> None: self.assertEqual(p[b"param"], b"encoded message") + def test_rejects_oversized_rfc_2231_index(self) -> None: + t, p = parse_options_header("text/plain; filename*" + ("1" * 4301) + "*=utf-8''x") + + self.assertEqual(t, b"text/plain") + self.assertEqual(p, {}) + class TestBaseParser(unittest.TestCase): def setUp(self) -> None: From 6bb95ffbfdfc6e6fc54113c0817a97eb912edb83 Mon Sep 17 00:00:00 2001 From: manunio Date: Sat, 25 Apr 2026 19:59:05 +0530 Subject: [PATCH 2/4] Fix parse_options_header to handle TypeError and add test for mixed RFC 2231 continuations --- python_multipart/multipart.py | 2 +- tests/test_multipart.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index 774b48e..8e73e74 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -173,7 +173,7 @@ def parse_options_header(value: str | bytes | None) -> tuple[bytes, dict[bytes, message["content-type"] = value try: params = message.get_params() - except ValueError: + except (TypeError, ValueError): return (value.split(";", 1)[0].lower().strip().encode("latin-1"), {}) # If there were no parameters, this would have already returned above assert params, "At least the content type value should be present" diff --git a/tests/test_multipart.py b/tests/test_multipart.py index ed685a3..a7eb6e6 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -310,6 +310,12 @@ def test_rejects_oversized_rfc_2231_index(self) -> None: self.assertEqual(t, b"text/plain") self.assertEqual(p, {}) + def test_rejects_mixed_rfc_2231_continuations(self) -> None: + t, p = parse_options_header("text/plain; filename*=utf-8''a; filename*0*=utf-8''b") + + self.assertEqual(t, b"text/plain") + self.assertEqual(p, {}) + class TestBaseParser(unittest.TestCase): def setUp(self) -> None: From 0b6fa9647f3623f435dd160427aaf5292a7cfa98 Mon Sep 17 00:00:00 2001 From: manunio Date: Sat, 25 Apr 2026 23:08:55 +0530 Subject: [PATCH 3/4] Adjust mixed RFC2231 continuation test to accept Python 3.12/3.13 parser differences. --- python_multipart/multipart.py | 2 +- tests/test_multipart.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index 8e73e74..3b7d385 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -174,7 +174,7 @@ def parse_options_header(value: str | bytes | None) -> tuple[bytes, dict[bytes, try: params = message.get_params() except (TypeError, ValueError): - return (value.split(";", 1)[0].lower().strip().encode("latin-1"), {}) + return (value.lower().strip().encode("latin-1"), {}) # If there were no parameters, this would have already returned above assert params, "At least the content type value should be present" ctype = params.pop(0)[0].encode("latin-1") diff --git a/tests/test_multipart.py b/tests/test_multipart.py index a7eb6e6..b541ab1 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -304,17 +304,17 @@ def test_handles_rfc_2231(self) -> None: self.assertEqual(p[b"param"], b"encoded message") - def test_rejects_oversized_rfc_2231_index(self) -> None: + def test_handles_oversized_rfc_2231_index(self) -> None: t, p = parse_options_header("text/plain; filename*" + ("1" * 4301) + "*=utf-8''x") - self.assertEqual(t, b"text/plain") + self.assertEqual(t, b"text/plain; filename*" + (b"1" * 4301) + b"*=utf-8''x") self.assertEqual(p, {}) - def test_rejects_mixed_rfc_2231_continuations(self) -> None: + def test_handles_mixed_rfc_2231_continuations(self) -> None: t, p = parse_options_header("text/plain; filename*=utf-8''a; filename*0*=utf-8''b") - self.assertEqual(t, b"text/plain") - self.assertEqual(p, {}) + self.assertIn(t, (b"text/plain", b"text/plain; filename*=utf-8''a; filename*0*=utf-8''b")) + self.assertIn(p, ({}, {b"filename": b"b"})) class TestBaseParser(unittest.TestCase): From 27e06a69de09b83b743ed57444ff7725d8a52f6f Mon Sep 17 00:00:00 2001 From: manunio Date: Mon, 27 Apr 2026 19:35:32 +0530 Subject: [PATCH 4/4] Update cifuzz actions --- .github/workflows/cifuzz.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 7a8b28e..ba7e053 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -25,13 +25,13 @@ jobs: steps: - name: Build Fuzzers id: build - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@675ddfb89ae1c614f1dfa99d18b91cd6d1d6b88b # master 2026-04-10 + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@9ff5089dbb11800055b6bc1af919a84b06dee2c8 # master 2026-04-27 with: oss-fuzz-project-name: "python-multipart" language: python - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@675ddfb89ae1c614f1dfa99d18b91cd6d1d6b88b # master 2026-04-10 + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@9ff5089dbb11800055b6bc1af919a84b06dee2c8 # master 2026-04-27 with: oss-fuzz-project-name: "python-multipart" language: python