diff --git a/00490-cve-2026-15308.patch b/00490-cve-2026-15308.patch new file mode 100644 index 0000000..df9bbd5 --- /dev/null +++ b/00490-cve-2026-15308.patch @@ -0,0 +1,116 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Sat, 4 Jul 2026 20:08:05 +0200 +Subject: 00490: CVE-2026-15308 + +pythongh-153030: Fix quadratic complexity in incremental parsing in HTMLParser (GH-153031) (GH-153039) + +When an unterminated construct (e.g. a tag or comment) spanned many +feed() calls, rescanning the growing buffer and concatenating new data +onto it were both quadratic. New data is now accumulated in a list and +only joined and parsed once enough has piled up. +(cherry picked from commit bcf98ddbc40ec9b3ee87da0124a5660b19b7e606) + +Co-authored-by: Serhiy Storchaka +Co-authored-by: Claude Opus 4.8 +--- + Lib/html/parser.py | 32 +++++++++++++++++-- + Lib/test/test_htmlparser.py | 20 ++++++++++++ + ...-07-04-17-00-00.gh-issue-153030.RovkP6.rst | 3 ++ + 3 files changed, 53 insertions(+), 2 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst + +diff --git a/Lib/html/parser.py b/Lib/html/parser.py +index 80fb8c3f92..f8ff4bb1fc 100644 +--- a/Lib/html/parser.py ++++ b/Lib/html/parser.py +@@ -157,6 +157,9 @@ def reset(self): + self.cdata_elem = None + self._support_cdata = True + self._escapable = True ++ self._pending = [] ++ self._pending_len = 0 ++ self._parse_threshold = 1 + super().reset() + + def feed(self, data): +@@ -165,11 +168,36 @@ def feed(self, data): + Call this as often as you want, with as little or as much text + as you want (may include '\n'). + """ +- self.rawdata = self.rawdata + data +- self.goahead(0) ++ # Accumulate new data in a list and only join and parse it once ++ # enough has piled up. Rescanning an unparsed buffer (e.g. an ++ # unterminated tag) and concatenating onto it on every call would ++ # both be quadratic in the input size. ++ self._pending_len += len(data) ++ if self._pending_len < self._parse_threshold: ++ self._pending.append(data) ++ else: ++ if not self._pending: ++ self.rawdata += data ++ else: ++ self._pending.append(data) ++ self.rawdata += ''.join(self._pending) ++ self._pending.clear() ++ self._pending_len = 0 ++ n = len(self.rawdata) ++ self.goahead(0) ++ if len(self.rawdata) < n: ++ # Some data was parsed; resume on the next call. ++ self._parse_threshold = 1 ++ else: ++ # Nothing was parsed; wait until the buffer doubles. ++ self._parse_threshold = len(self.rawdata) + + def close(self): + """Handle any buffered data.""" ++ if self._pending: ++ self.rawdata += ''.join(self._pending) ++ self._pending.clear() ++ self._pending_len = 0 + self.goahead(1) + + __starttag_text = None +diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py +index e4eff1ea17..54bbf11f69 100644 +--- a/Lib/test/test_htmlparser.py ++++ b/Lib/test/test_htmlparser.py +@@ -1031,6 +1031,26 @@ def check(source): + check("") # comment ++ check("") # processing instruction ++ check("") # doctype ++ check("") # CDATA section ++ check("") # start tag ++ check("") # RAWTEXT element ++ + + class AttributesTestCase(TestCaseBase): + +diff --git a/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst b/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst +new file mode 100644 +index 0000000000..d1d60593f4 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst +@@ -0,0 +1,3 @@ ++Fixed quadratic complexity in incremental parsing of long unterminated ++constructs (such as tags or comments) in :class:`html.parser.HTMLParser`, ++which could be exploited for a denial of service. diff --git a/python3.14.spec b/python3.14.spec index 3bdc59c..aa9dab2 100644 --- a/python3.14.spec +++ b/python3.14.spec @@ -49,7 +49,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 1%{?dist}.1 License: Python-2.0.1 @@ -443,6 +443,17 @@ Patch477: 00477-raise-an-error-when-importing-stdlib-modules-compiled-for-a-diff # Resolved upstream: https://github.com/python/cpython/issues/149144 Patch487: 00487-fixup-for-CVE-2026-6019.patch +# 00490 # 3e8c5ad70d6a515107352d8779269240a0553f54 +# CVE-2026-15308 +# +# pythongh-153030: Fix quadratic complexity in incremental parsing in HTMLParser (GH-153031) (GH-153039) +# +# When an unterminated construct (e.g. a tag or comment) spanned many +# feed() calls, rescanning the growing buffer and concatenating new data +# onto it were both quadratic. New data is now accumulated in a list and +# only joined and parsed once enough has piled up. +Patch490: 00490-cve-2026-15308.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1980,6 +1991,10 @@ CheckPython freethreading # ====================================================== %changelog +* Fri Jul 10 2026 Tomáš Hrnčiar - 3.14.5-1.1 +- Security fix for CVE-2026-15308 +Resolves: RHEL-193775 + * Tue Jun 09 2026 Miro Hrončok - 3.14.5-1 - Update to 3.14.5 Resolves: RHEL-176147