From 52f0e76d33b4a7e54af27189b5bcc90290d2b4a1 Mon Sep 17 00:00:00 2001 From: desert-sailor Date: Tue, 22 Jul 2025 09:53:53 +0800 Subject: [PATCH] Fix CVE-2025-54121 --- CVE-2025-54121.patch | 56 +++++++++++++++++++++++++++++++++++++++++++ python-starlette.spec | 7 ++++-- 2 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 CVE-2025-54121.patch diff --git a/CVE-2025-54121.patch b/CVE-2025-54121.patch new file mode 100644 index 0000000..3b8ce93 --- /dev/null +++ b/CVE-2025-54121.patch @@ -0,0 +1,56 @@ +From 9f7ec2eb512fcc3fe90b43cb9dd9e1d08696bec1 Mon Sep 17 00:00:00 2001 +From: Michael Honaker <37811263+HonakerM@users.noreply.github.com> +Date: Mon, 21 Jul 2025 02:24:02 +0900 +Subject: [PATCH] Make UploadFile check for future rollover + +--- + starlette/datastructures.py | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/starlette/datastructures.py b/starlette/datastructures.py +index f5d74d2..9957090 100644 +--- a/starlette/datastructures.py ++++ b/starlette/datastructures.py +@@ -424,6 +424,10 @@ class UploadFile: + self.size = size + self.headers = headers or Headers() + ++ # Capture max size from SpooledTemporaryFile if one is provided. This slightly speeds up future checks. ++ # Note 0 means unlimited mirroring SpooledTemporaryFile's __init__ ++ self._max_mem_size = getattr(self.file, "_max_size", 0) ++ + @property + def content_type(self) -> str | None: + return self.headers.get("content-type", None) +@@ -434,14 +438,24 @@ class UploadFile: + rolled_to_disk = getattr(self.file, "_rolled", True) + return not rolled_to_disk + ++ def _will_roll(self, size_to_add: int) -> bool: ++ # If we're not in_memory then we will always roll ++ if not self._in_memory: ++ return True ++ ++ # Check for SpooledTemporaryFile._max_size ++ future_size = self.file.tell() + size_to_add ++ return bool(future_size > self._max_mem_size) if self._max_mem_size else False ++ + async def write(self, data: bytes) -> None: ++ new_data_len = len(data) + if self.size is not None: +- self.size += len(data) ++ self.size += new_data_len + +- if self._in_memory: +- self.file.write(data) +- else: ++ if self._will_roll(new_data_len): + await run_in_threadpool(self.file.write, data) ++ else: ++ self.file.write(data) + + async def read(self, size: int = -1) -> bytes: + if self._in_memory: +-- +2.43.0 + diff --git a/python-starlette.spec b/python-starlette.spec index aab0baa..29ec254 100644 --- a/python-starlette.spec +++ b/python-starlette.spec @@ -1,12 +1,12 @@ Name: python-starlette Version: 0.46.1 -Release: 2 +Release: 3 Summary: The little ASGI library that shines License: BSD-3-Clause URL: https://www.starlette.io/ Source: https://github.com/encode/starlette/archive/%{version}/starlette-%{version}.tar.gz - +Patch1: CVE-2025-54121.patch BuildArch: noarch BuildRequires: python3-devel @@ -95,6 +95,9 @@ k="${k-}${k+ and }not test_lifespan_with_on_events" %changelog +* Tue Jul 22 2025 Dongxing Wang - 0.46.1-3 +- Fix CVE-2025-54121 + * Thu Mar 13 2025 Ge Wang - 0.46.1-2 - Remove invalid patch due to dependency updated -- Gitee