new file mode 100644
@@ -0,0 +1,40 @@
+From 151ba03ad569ec1c13593899550f4ab7d1fa03c8 Mon Sep 17 00:00:00 2001
+From: Ben Darnell <ben@bendarnell.com>
+Date: Wed, 5 Aug 2026 14:13:32 -0400
+Subject: [PATCH] httputil: Apply multipart max_parts limit earlier
+
+This prevents some CPU and memory amplification attacks.
+
+(cherry picked from commit de85b3f87446e323e881bbaa3d5a74f4b76e5f05)
+
+CVE: CVE-2026-91990
+Upstream-Status: Backport [https://github.com/tornadoweb/tornado/commit/de85b3f87446e323e881bbaa3d5a74f4b76e5f05]
+
+Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
+---
+ tornado/httputil.py | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/tornado/httputil.py b/tornado/httputil.py
+index 0c9ad832..f698db21 100644
+--- a/tornado/httputil.py
++++ b/tornado/httputil.py
+@@ -37,7 +37,6 @@ from urllib.parse import urlencode, urlparse, urlunparse, parse_qsl
+ from tornado.escape import native_str, parse_qs_bytes, utf8, to_unicode
+ from tornado.util import ObjectDict, unicode_type
+
+-
+ # responses is unused in this file, but we re-export it to other files.
+ # Reference it so pyflakes doesn't complain.
+ responses
+@@ -1078,7 +1077,9 @@ def parse_multipart_form_data(
+ final_boundary_index = data.rfind(b"--" + boundary + b"--")
+ if final_boundary_index == -1:
+ raise HTTPInputError("Invalid multipart/form-data: no final boundary found")
+- parts = data[:final_boundary_index].split(b"--" + boundary + b"\r\n")
++ parts = data[:final_boundary_index].split(
++ b"--" + boundary + b"\r\n", config.max_parts + 1
++ )
+ if len(parts) > config.max_parts:
+ raise HTTPInputError("multipart/form-data has too many parts")
+ for part in parts:
@@ -8,6 +8,9 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57"
SRC_URI[sha256sum] = "66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2"
+SRC_URI += "file://CVE-2026-91990.patch \
+"
+
inherit pypi python_setuptools_build_meta
# Requires _compression which is currently located in misc