From ed5f99f713ebcaf809f11514b4903df36c888db3 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Mon, 30 Mar 2026 10:03:03 -0400 Subject: [PATCH] import CS python3.9-3.9.25-5.el9 --- .gitignore | 2 +- .python3.9.metadata | 2 +- SOURCES/00189-use-rpm-wheels.patch | 4 +- SOURCES/00397-tarfile-filter.patch | 28 ++-- SOURCES/00467-CVE-2025-8194.patch | 215 ----------------------------- SOURCES/00471-cve-2025-12084.patch | 140 +++++++++++++++++++ SOURCES/00473-cve-2026-0865.patch | 90 ++++++++++++ SOURCES/00474-cve-2025-15366.patch | 61 ++++++++ SOURCES/00475-cve-2025-15367.patch | 61 ++++++++ SOURCES/00476-cve-2026-1299.patch | 108 +++++++++++++++ SOURCES/Python-3.9.23.tar.xz.asc | 16 --- SOURCES/Python-3.9.25.tar.xz.asc | 16 +++ SPECS/python3.9.spec | 78 +++++++++-- 13 files changed, 563 insertions(+), 258 deletions(-) delete mode 100644 SOURCES/00467-CVE-2025-8194.patch create mode 100644 SOURCES/00471-cve-2025-12084.patch create mode 100644 SOURCES/00473-cve-2026-0865.patch create mode 100644 SOURCES/00474-cve-2025-15366.patch create mode 100644 SOURCES/00475-cve-2025-15367.patch create mode 100644 SOURCES/00476-cve-2026-1299.patch delete mode 100644 SOURCES/Python-3.9.23.tar.xz.asc create mode 100644 SOURCES/Python-3.9.25.tar.xz.asc diff --git a/.gitignore b/.gitignore index ad441f6..e45d6ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/Python-3.9.23.tar.xz +SOURCES/Python-3.9.25.tar.xz diff --git a/.python3.9.metadata b/.python3.9.metadata index 6062d60..3b7f785 100644 --- a/.python3.9.metadata +++ b/.python3.9.metadata @@ -1 +1 @@ -73d07237b70b19e4cd530bbc204cccd668ec05d4 SOURCES/Python-3.9.23.tar.xz +36c7257ec30dca042679626d0dff79715acd4efb SOURCES/Python-3.9.25.tar.xz diff --git a/SOURCES/00189-use-rpm-wheels.patch b/SOURCES/00189-use-rpm-wheels.patch index ccc8245..774aca6 100644 --- a/SOURCES/00189-use-rpm-wheels.patch +++ b/SOURCES/00189-use-rpm-wheels.patch @@ -12,7 +12,7 @@ We might eventually pursuit upstream support, but it's low prio 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py -index e510cc7..5bd16a6 100644 +index d61bb089e3..77d7ec5a65 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -1,3 +1,5 @@ @@ -30,7 +30,7 @@ index e510cc7..5bd16a6 100644 __all__ = ["version", "bootstrap"] --_SETUPTOOLS_VERSION = "58.1.0" +-_SETUPTOOLS_VERSION = "79.0.1" -_PIP_VERSION = "23.0.1" + +_WHEEL_DIR = "/usr/share/python-wheels/" diff --git a/SOURCES/00397-tarfile-filter.patch b/SOURCES/00397-tarfile-filter.patch index 3851cb6..fd984b6 100644 --- a/SOURCES/00397-tarfile-filter.patch +++ b/SOURCES/00397-tarfile-filter.patch @@ -1,8 +1,8 @@ -From 8b70605b594b3831331a9340ba764ff751871612 Mon Sep 17 00:00:00 2001 +From fc3e5ff91495aaf9905bd38ac61db0c3279d17e0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin -Date: Mon, 6 Mar 2023 17:24:24 +0100 -Subject: [PATCH 2/2] CVE-2007-4559, PEP-706: Add filters for tarfile - extraction (downstream) +Date: Fri, 21 Nov 2025 14:30:02 +0100 +Subject: [PATCH] CVE-2007-4559, PEP-706: Add filters for tarfile extraction + (downstream) Add and test RHEL-specific ways of configuring the default behavior: environment variable and config file. @@ -13,7 +13,7 @@ variable and config file. 3 files changed, 169 insertions(+), 4 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py -index b6ad7dbe2a4..dc7050b2c63 100755 +index 209c206..fa3f922 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -72,6 +72,13 @@ __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError", @@ -30,7 +30,7 @@ index b6ad7dbe2a4..dc7050b2c63 100755 #--------------------------------------------------------- # tar constants -@@ -2197,6 +2204,41 @@ class TarFile(object): +@@ -2253,6 +2260,41 @@ class TarFile(object): if filter is None: filter = self.extraction_filter if filter is None: @@ -73,7 +73,7 @@ index b6ad7dbe2a4..dc7050b2c63 100755 if isinstance(filter, str): raise TypeError( diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py -index 9041e7aa368..1eb1116cc10 100644 +index 9041e7a..1eb1116 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1613,7 +1613,8 @@ class TestArchives(BaseTest, unittest.TestCase): @@ -87,10 +87,10 @@ index 9041e7aa368..1eb1116cc10 100644 def test_unpack_archive_tar(self): diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index a66f7efd2d6..6fd3c384b5c 100644 +index 17d2239..8b9aea2 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py -@@ -2,7 +2,7 @@ import sys +@@ -3,7 +3,7 @@ import sys import os import io from hashlib import sha256 @@ -99,7 +99,7 @@ index a66f7efd2d6..6fd3c384b5c 100644 from random import Random import pathlib import shutil -@@ -2929,7 +2929,11 @@ class NoneInfoExtractTests(ReadTest): +@@ -2999,7 +2999,11 @@ class NoneInfoExtractTests(ReadTest): tar = tarfile.open(tarname, mode='r', encoding="iso8859-1") cls.control_dir = pathlib.Path(TEMPDIR) / "extractall_ctrl" tar.errorlevel = 0 @@ -112,7 +112,7 @@ index a66f7efd2d6..6fd3c384b5c 100644 tar.close() cls.control_paths = set( p.relative_to(cls.control_dir) -@@ -3592,7 +3596,8 @@ class TestExtractionFilters(unittest.TestCase): +@@ -4065,7 +4069,8 @@ class TestExtractionFilters(unittest.TestCase): """Ensure the default filter does not warn (like in 3.12)""" with ArchiveMaker() as arc: arc.add('foo') @@ -122,8 +122,8 @@ index a66f7efd2d6..6fd3c384b5c 100644 with self.check_context(arc.open(), None): self.expect_file('foo') -@@ -3762,6 +3767,123 @@ class TestExtractionFilters(unittest.TestCase): - self.expect_exception(TypeError) # errorlevel is not int +@@ -4390,6 +4395,123 @@ class OffsetValidationTests(unittest.TestCase): + self.assertEqual(members[0].offset, expected_offset) + @contextmanager @@ -247,5 +247,5 @@ index a66f7efd2d6..6fd3c384b5c 100644 support.unlink(TEMPDIR) os.makedirs(TEMPDIR) -- -2.40.1 +2.51.1 diff --git a/SOURCES/00467-CVE-2025-8194.patch b/SOURCES/00467-CVE-2025-8194.patch deleted file mode 100644 index 01159f6..0000000 --- a/SOURCES/00467-CVE-2025-8194.patch +++ /dev/null @@ -1,215 +0,0 @@ -From eda136637fc7f056b403e1797a9b0403d6914d9e Mon Sep 17 00:00:00 2001 -From: Alexander Urieles -Date: Tue, 19 Aug 2025 12:18:15 +0200 -Subject: [PATCH] gh-130577: tarfile now validates archives to ensure member - offsets are non-negative (GH-137027) - -Co-authored-by: Gregory P. Smith -(cherry picked from commit 7040aa54f14676938970e10c5f74ea93cd56aa38) ---- - Lib/tarfile.py | 3 + - Lib/test/test_tarfile.py | 156 ++++++++++++++++++ - ...-07-23-00-35-29.gh-issue-130577.c7EITy.rst | 3 + - 3 files changed, 162 insertions(+) - create mode 100644 Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst - -diff --git a/Lib/tarfile.py b/Lib/tarfile.py -index 21ffd83..fa3f922 100755 ---- a/Lib/tarfile.py -+++ b/Lib/tarfile.py -@@ -1609,6 +1609,9 @@ class TarInfo(object): - """Round up a byte count by BLOCKSIZE and return it, - e.g. _block(834) => 1024. - """ -+ # Only non-negative offsets are allowed -+ if count < 0: -+ raise InvalidHeaderError("invalid offset") - blocks, remainder = divmod(count, BLOCKSIZE) - if remainder: - blocks += 1 -diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index 29f65d0..0bba25a 100644 ---- a/Lib/test/test_tarfile.py -+++ b/Lib/test/test_tarfile.py -@@ -48,6 +48,7 @@ bz2name = os.path.join(TEMPDIR, "testtar.tar.bz2") - xzname = os.path.join(TEMPDIR, "testtar.tar.xz") - tmpname = os.path.join(TEMPDIR, "tmp.tar") - dotlessname = os.path.join(TEMPDIR, "testtar") -+SPACE = b" " - - sha256_regtype = ( - "e09e4bc8b3c9d9177e77256353b36c159f5f040531bbd4b024a8f9b9196c71ce" -@@ -4356,6 +4357,161 @@ class TestExtractionFilters(unittest.TestCase): - self.check_trusted_default(tar, tempdir) - - -+class OffsetValidationTests(unittest.TestCase): -+ tarname = tmpname -+ invalid_posix_header = ( -+ # name: 100 bytes -+ tarfile.NUL * tarfile.LENGTH_NAME -+ # mode, space, null terminator: 8 bytes -+ + b"000755" + SPACE + tarfile.NUL -+ # uid, space, null terminator: 8 bytes -+ + b"000001" + SPACE + tarfile.NUL -+ # gid, space, null terminator: 8 bytes -+ + b"000001" + SPACE + tarfile.NUL -+ # size, space: 12 bytes -+ + b"\xff" * 11 + SPACE -+ # mtime, space: 12 bytes -+ + tarfile.NUL * 11 + SPACE -+ # chksum: 8 bytes -+ + b"0011407" + tarfile.NUL -+ # type: 1 byte -+ + tarfile.REGTYPE -+ # linkname: 100 bytes -+ + tarfile.NUL * tarfile.LENGTH_LINK -+ # magic: 6 bytes, version: 2 bytes -+ + tarfile.POSIX_MAGIC -+ # uname: 32 bytes -+ + tarfile.NUL * 32 -+ # gname: 32 bytes -+ + tarfile.NUL * 32 -+ # devmajor, space, null terminator: 8 bytes -+ + tarfile.NUL * 6 + SPACE + tarfile.NUL -+ # devminor, space, null terminator: 8 bytes -+ + tarfile.NUL * 6 + SPACE + tarfile.NUL -+ # prefix: 155 bytes -+ + tarfile.NUL * tarfile.LENGTH_PREFIX -+ # padding: 12 bytes -+ + tarfile.NUL * 12 -+ ) -+ invalid_gnu_header = ( -+ # name: 100 bytes -+ tarfile.NUL * tarfile.LENGTH_NAME -+ # mode, null terminator: 8 bytes -+ + b"0000755" + tarfile.NUL -+ # uid, null terminator: 8 bytes -+ + b"0000001" + tarfile.NUL -+ # gid, space, null terminator: 8 bytes -+ + b"0000001" + tarfile.NUL -+ # size, space: 12 bytes -+ + b"\xff" * 11 + SPACE -+ # mtime, space: 12 bytes -+ + tarfile.NUL * 11 + SPACE -+ # chksum: 8 bytes -+ + b"0011327" + tarfile.NUL -+ # type: 1 byte -+ + tarfile.REGTYPE -+ # linkname: 100 bytes -+ + tarfile.NUL * tarfile.LENGTH_LINK -+ # magic: 8 bytes -+ + tarfile.GNU_MAGIC -+ # uname: 32 bytes -+ + tarfile.NUL * 32 -+ # gname: 32 bytes -+ + tarfile.NUL * 32 -+ # devmajor, null terminator: 8 bytes -+ + tarfile.NUL * 8 -+ # devminor, null terminator: 8 bytes -+ + tarfile.NUL * 8 -+ # padding: 167 bytes -+ + tarfile.NUL * 167 -+ ) -+ invalid_v7_header = ( -+ # name: 100 bytes -+ tarfile.NUL * tarfile.LENGTH_NAME -+ # mode, space, null terminator: 8 bytes -+ + b"000755" + SPACE + tarfile.NUL -+ # uid, space, null terminator: 8 bytes -+ + b"000001" + SPACE + tarfile.NUL -+ # gid, space, null terminator: 8 bytes -+ + b"000001" + SPACE + tarfile.NUL -+ # size, space: 12 bytes -+ + b"\xff" * 11 + SPACE -+ # mtime, space: 12 bytes -+ + tarfile.NUL * 11 + SPACE -+ # chksum: 8 bytes -+ + b"0010070" + tarfile.NUL -+ # type: 1 byte -+ + tarfile.REGTYPE -+ # linkname: 100 bytes -+ + tarfile.NUL * tarfile.LENGTH_LINK -+ # padding: 255 bytes -+ + tarfile.NUL * 255 -+ ) -+ valid_gnu_header = tarfile.TarInfo("filename").tobuf(tarfile.GNU_FORMAT) -+ data_block = b"\xff" * tarfile.BLOCKSIZE -+ -+ def _write_buffer(self, buffer): -+ with open(self.tarname, "wb") as f: -+ f.write(buffer) -+ -+ def _get_members(self, ignore_zeros=None): -+ with open(self.tarname, "rb") as f: -+ with tarfile.open( -+ mode="r", fileobj=f, ignore_zeros=ignore_zeros -+ ) as tar: -+ return tar.getmembers() -+ -+ def _assert_raises_read_error_exception(self): -+ with self.assertRaisesRegex( -+ tarfile.ReadError, "file could not be opened successfully" -+ ): -+ self._get_members() -+ -+ def test_invalid_offset_header_validations(self): -+ for tar_format, invalid_header in ( -+ ("posix", self.invalid_posix_header), -+ ("gnu", self.invalid_gnu_header), -+ ("v7", self.invalid_v7_header), -+ ): -+ with self.subTest(format=tar_format): -+ self._write_buffer(invalid_header) -+ self._assert_raises_read_error_exception() -+ -+ def test_early_stop_at_invalid_offset_header(self): -+ buffer = self.valid_gnu_header + self.invalid_gnu_header + self.valid_gnu_header -+ self._write_buffer(buffer) -+ members = self._get_members() -+ self.assertEqual(len(members), 1) -+ self.assertEqual(members[0].name, "filename") -+ self.assertEqual(members[0].offset, 0) -+ -+ def test_ignore_invalid_archive(self): -+ # 3 invalid headers with their respective data -+ buffer = (self.invalid_gnu_header + self.data_block) * 3 -+ self._write_buffer(buffer) -+ members = self._get_members(ignore_zeros=True) -+ self.assertEqual(len(members), 0) -+ -+ def test_ignore_invalid_offset_headers(self): -+ for first_block, second_block, expected_offset in ( -+ ( -+ (self.valid_gnu_header), -+ (self.invalid_gnu_header + self.data_block), -+ 0, -+ ), -+ ( -+ (self.invalid_gnu_header + self.data_block), -+ (self.valid_gnu_header), -+ 1024, -+ ), -+ ): -+ self._write_buffer(first_block + second_block) -+ members = self._get_members(ignore_zeros=True) -+ self.assertEqual(len(members), 1) -+ self.assertEqual(members[0].name, "filename") -+ self.assertEqual(members[0].offset, expected_offset) -+ -+ - def setUpModule(): - support.unlink(TEMPDIR) - os.makedirs(TEMPDIR) -diff --git a/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst b/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst -new file mode 100644 -index 0000000..342cabb ---- /dev/null -+++ b/Misc/NEWS.d/next/Library/2025-07-23-00-35-29.gh-issue-130577.c7EITy.rst -@@ -0,0 +1,3 @@ -+:mod:`tarfile` now validates archives to ensure member offsets are -+non-negative. (Contributed by Alexander Enrique Urieles Nieto in -+:gh:`130577`.) --- -2.50.1 - diff --git a/SOURCES/00471-cve-2025-12084.patch b/SOURCES/00471-cve-2025-12084.patch new file mode 100644 index 0000000..78c49fd --- /dev/null +++ b/SOURCES/00471-cve-2025-12084.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Mon, 22 Dec 2025 14:48:49 +0100 +Subject: 00471: CVE-2025-12084 + +* gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146) +* gh-142754: Ensure that Element & Attr instances have the ownerDocument attribute (GH-142794) +(cherry picked from commit 1cc7551b3f9f71efbc88d96dce90f82de98b2454) +(cherry picked from commit 08d8e18ad81cd45bc4a27d6da478b51ea49486e4) +(cherry picked from commit 8d2d7bb2e754f8649a68ce4116271a4932f76907) + +Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com> +Co-authored-by: Seth Michael Larson +Co-authored-by: Petr Viktorin +Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> +Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> +Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> +Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> +Co-authored-by: Gregory P. Smith +--- + Lib/test/test_minidom.py | 33 ++++++++++++++++++- + Lib/xml/dom/minidom.py | 11 ++----- + ...-12-01-09-36-45.gh-issue-142145.tcAUhg.rst | 6 ++++ + 3 files changed, 41 insertions(+), 9 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst + +diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py +index 97620258d8..9f7f5b240e 100644 +--- a/Lib/test/test_minidom.py ++++ b/Lib/test/test_minidom.py +@@ -2,6 +2,7 @@ + + import copy + import pickle ++import time + import io + from test import support + import unittest +@@ -9,7 +10,7 @@ import unittest + import pyexpat + import xml.dom.minidom + +-from xml.dom.minidom import parse, Node, Document, parseString ++from xml.dom.minidom import parse, Attr, Node, Document, Element, parseString + from xml.dom.minidom import getDOMImplementation + from xml.parsers.expat import ExpatError + +@@ -163,6 +164,36 @@ class MinidomTest(unittest.TestCase): + self.confirm(dom.documentElement.childNodes[-1].data == "Hello") + dom.unlink() + ++ @support.requires_resource('cpu') ++ def testAppendChildNoQuadraticComplexity(self): ++ impl = getDOMImplementation() ++ ++ newdoc = impl.createDocument(None, "some_tag", None) ++ top_element = newdoc.documentElement ++ children = [newdoc.createElement(f"child-{i}") for i in range(1, 2 ** 15 + 1)] ++ element = top_element ++ ++ start = time.monotonic() ++ for child in children: ++ element.appendChild(child) ++ element = child ++ end = time.monotonic() ++ ++ # This example used to take at least 30 seconds. ++ # Conservative assertion due to the wide variety of systems and ++ # build configs timing based tests wind up run under. ++ # A --with-address-sanitizer --with-pydebug build on a rpi5 still ++ # completes this loop in <0.5 seconds. ++ self.assertLess(end - start, 4) ++ ++ def testSetAttributeNodeWithoutOwnerDocument(self): ++ # regression test for gh-142754 ++ elem = Element("test") ++ attr = Attr("id") ++ attr.value = "test-id" ++ elem.setAttributeNode(attr) ++ self.assertEqual(elem.getAttribute("id"), "test-id") ++ + def testAppendChildFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.appendChild(frag) +diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py +index d09ef5e7d0..e4e8b42996 100644 +--- a/Lib/xml/dom/minidom.py ++++ b/Lib/xml/dom/minidom.py +@@ -292,13 +292,6 @@ def _append_child(self, node): + childNodes.append(node) + node.parentNode = self + +-def _in_document(node): +- # return True iff node is part of a document tree +- while node is not None: +- if node.nodeType == Node.DOCUMENT_NODE: +- return True +- node = node.parentNode +- return False + + def _write_data(writer, data): + "Writes datachars to writer." +@@ -355,6 +348,7 @@ class Attr(Node): + def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, + prefix=None): + self.ownerElement = None ++ self.ownerDocument = None + self._name = qName + self.namespaceURI = namespaceURI + self._prefix = prefix +@@ -678,6 +672,7 @@ class Element(Node): + + def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None, + localName=None): ++ self.ownerDocument = None + self.parentNode = None + self.tagName = self.nodeName = tagName + self.prefix = prefix +@@ -1537,7 +1532,7 @@ def _clear_id_cache(node): + if node.nodeType == Node.DOCUMENT_NODE: + node._id_cache.clear() + node._id_search_stack = None +- elif _in_document(node): ++ elif node.ownerDocument: + node.ownerDocument._id_cache.clear() + node.ownerDocument._id_search_stack= None + +diff --git a/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst +new file mode 100644 +index 0000000000..05c7df35d1 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst +@@ -0,0 +1,6 @@ ++Remove quadratic behavior in ``xml.minidom`` node ID cache clearing. In order ++to do this without breaking existing users, we also add the *ownerDocument* ++attribute to :mod:`xml.dom.minidom` elements and attributes created by directly ++instantiating the ``Element`` or ``Attr`` class. Note that this way of creating ++nodes is not supported; creator functions like ++:py:meth:`xml.dom.Document.documentElement` should be used instead. diff --git a/SOURCES/00473-cve-2026-0865.patch b/SOURCES/00473-cve-2026-0865.patch new file mode 100644 index 0000000..2df7803 --- /dev/null +++ b/SOURCES/00473-cve-2026-0865.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Sat, 17 Jan 2026 11:46:21 -0600 +Subject: 00473: CVE-2026-0865 + + gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) + +* Add 'test.support' fixture for C0 control characters +* gh-143916: Reject control characters in wsgiref.headers.Headers +--- + Lib/test/support/__init__.py | 7 +++++++ + Lib/test/test_wsgiref.py | 12 +++++++++++- + Lib/wsgiref/headers.py | 3 +++ + .../2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst | 2 ++ + 4 files changed, 23 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst + +diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py +index e991426bd3..94446da6c9 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -3340,3 +3340,10 @@ def adjust_int_max_str_digits(max_digits): + yield + finally: + sys.set_int_max_str_digits(current) ++ ++ ++def control_characters_c0() -> list[str]: ++ """Returns a list of C0 control characters as strings. ++ C0 control characters defined as the byte range 0x00-0x1F, and 0x7F. ++ """ ++ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"] +diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py +index 3e76e01c65..d5d3f650a1 100644 +--- a/Lib/test/test_wsgiref.py ++++ b/Lib/test/test_wsgiref.py +@@ -1,6 +1,6 @@ + from unittest import mock + from test import support +-from test.support import socket_helper ++from test.support import socket_helper, control_characters_c0 + from test.test_httpservers import NoLogRequestHandler + from unittest import TestCase + from wsgiref.util import setup_testing_defaults +@@ -526,6 +526,16 @@ class HeaderTests(TestCase): + '\r\n' + ) + ++ def testRaisesControlCharacters(self): ++ headers = Headers() ++ for c0 in control_characters_c0(): ++ self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val") ++ self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}") ++ self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param") ++ self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param") ++ self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}") ++ ++ + class ErrorHandler(BaseCGIHandler): + """Simple handler subclass for testing BaseHandler""" + +diff --git a/Lib/wsgiref/headers.py b/Lib/wsgiref/headers.py +index fab851c5a4..fd98e85d75 100644 +--- a/Lib/wsgiref/headers.py ++++ b/Lib/wsgiref/headers.py +@@ -9,6 +9,7 @@ written by Barry Warsaw. + # existence of which force quoting of the parameter value. + import re + tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') ++_control_chars_re = re.compile(r'[\x00-\x1F\x7F]') + + def _formatparam(param, value=None, quote=1): + """Convenience function to format and return a key=value pair. +@@ -41,6 +42,8 @@ class Headers: + def _convert_string_type(self, value): + """Convert/check value type.""" + if type(value) is str: ++ if _control_chars_re.search(value): ++ raise ValueError("Control characters not allowed in headers") + return value + raise AssertionError("Header names/values must be" + " of type str (got {0})".format(repr(value))) +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst +new file mode 100644 +index 0000000000..44bd0b2705 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst +@@ -0,0 +1,2 @@ ++Reject C0 control characters within wsgiref.headers.Headers fields, values, ++and parameters. diff --git a/SOURCES/00474-cve-2025-15366.patch b/SOURCES/00474-cve-2025-15366.patch new file mode 100644 index 0000000..701600c --- /dev/null +++ b/SOURCES/00474-cve-2025-15366.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Tue, 20 Jan 2026 14:45:42 -0600 +Subject: 00474: CVE-2025-15366 + +gh-143921: Reject control characters in IMAP commands + +(cherry-picked from commit 6262704b134db2a4ba12e85ecfbd968534f28b45) +--- + Lib/imaplib.py | 4 +++- + Lib/test/test_imaplib.py | 6 ++++++ + .../Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst | 1 + + 3 files changed, 10 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst + +diff --git a/Lib/imaplib.py b/Lib/imaplib.py +index ced7203e0c..be2fcb3c05 100644 +--- a/Lib/imaplib.py ++++ b/Lib/imaplib.py +@@ -132,7 +132,7 @@ Untagged_status = re.compile( + # We compile these in _mode_xxx. + _Literal = br'.*{(?P\d+)}$' + _Untagged_status = br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?' +- ++_control_chars = re.compile(b'[\x00-\x1F\x7F]') + + + class IMAP4: +@@ -994,6 +994,8 @@ class IMAP4: + if arg is None: continue + if isinstance(arg, str): + arg = bytes(arg, self._encoding) ++ if _control_chars.search(arg): ++ raise ValueError("Control characters not allowed in commands") + data = data + b' ' + arg + + literal = self.literal +diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py +index 057e4e65f0..471325de1d 100644 +--- a/Lib/test/test_imaplib.py ++++ b/Lib/test/test_imaplib.py +@@ -503,6 +503,12 @@ class NewIMAPTestsMixin(): + self.assertEqual(data[0], b'LOGIN completed') + self.assertEqual(client.state, 'AUTH') + ++ def test_control_characters(self): ++ client, _ = self._setup(SimpleIMAPHandler) ++ for c0 in support.control_characters_c0(): ++ with self.assertRaises(ValueError): ++ client.login(f'user{c0}', 'pass') ++ + def test_logout(self): + client, _ = self._setup(SimpleIMAPHandler) + typ, data = client.login('user', 'pass') +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst +new file mode 100644 +index 0000000000..4e13fe92bc +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst +@@ -0,0 +1 @@ ++Reject control characters in IMAP commands. diff --git a/SOURCES/00475-cve-2025-15367.patch b/SOURCES/00475-cve-2025-15367.patch new file mode 100644 index 0000000..76bd511 --- /dev/null +++ b/SOURCES/00475-cve-2025-15367.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Tue, 20 Jan 2026 14:46:32 -0600 +Subject: 00475: CVE-2025-15367 + +gh-143923: Reject control characters in POP3 commands + +(cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) +--- + Lib/poplib.py | 2 ++ + Lib/test/test_poplib.py | 8 ++++++++ + .../2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst | 1 + + 3 files changed, 11 insertions(+) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst + +diff --git a/Lib/poplib.py b/Lib/poplib.py +index 0f8587317c..f563030f7f 100644 +--- a/Lib/poplib.py ++++ b/Lib/poplib.py +@@ -122,6 +122,8 @@ class POP3: + def _putcmd(self, line): + if self._debugging: print('*cmd*', repr(line)) + line = bytes(line, self.encoding) ++ if re.search(b'[\x00-\x1F\x7F]', line): ++ raise ValueError('Control characters not allowed in commands') + self._putline(line) + + +diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py +index 5d9f557eef..7a0313f35a 100644 +--- a/Lib/test/test_poplib.py ++++ b/Lib/test/test_poplib.py +@@ -14,6 +14,7 @@ import threading + import unittest + from unittest import TestCase, skipUnless + from test import support as test_support ++from test.support import control_characters_c0 + from test.support import hashlib_helper + from test.support import socket_helper + +@@ -360,6 +361,13 @@ class TestPOP3Class(TestCase): + self.assertIsNone(self.client.sock) + self.assertIsNone(self.client.file) + ++ def test_control_characters(self): ++ for c0 in control_characters_c0(): ++ with self.assertRaises(ValueError): ++ self.client.user(f'user{c0}') ++ with self.assertRaises(ValueError): ++ self.client.pass_(f'{c0}pass') ++ + @requires_ssl + def test_stls_capa(self): + capa = self.client.capa() +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +new file mode 100644 +index 0000000000..3cde4df3e0 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +@@ -0,0 +1 @@ ++Reject control characters in POP3 commands. diff --git a/SOURCES/00476-cve-2026-1299.patch b/SOURCES/00476-cve-2026-1299.patch new file mode 100644 index 0000000..528434d --- /dev/null +++ b/SOURCES/00476-cve-2026-1299.patch @@ -0,0 +1,108 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Sun, 25 Jan 2026 18:10:00 +0100 +Subject: 00476: CVE-2026-1299 + +gh-144125: email: verify headers are sound in BytesGenerator +(cherry picked from commit 052e55e7d44718fe46cbba0ca995cb8fcc359413) + +Co-authored-by: Seth Michael Larson +Co-authored-by: Denis Ledoux +Co-authored-by: Denis Ledoux <5822488+beledouxdenis@users.noreply.github.com> +Co-authored-by: Petr Viktorin <302922+encukou@users.noreply.github.com> +Co-authored-by: Bas Bloemsaat <1586868+basbloemsaat@users.noreply.github.com> +--- + Lib/email/generator.py | 12 +++++++++++- + Lib/test/test_email/test_generator.py | 4 +++- + Lib/test/test_email/test_policy.py | 6 +++++- + .../2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst | 4 ++++ + 4 files changed, 23 insertions(+), 3 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst + +diff --git a/Lib/email/generator.py b/Lib/email/generator.py +index 89224ae41c..98cc4a09c9 100644 +--- a/Lib/email/generator.py ++++ b/Lib/email/generator.py +@@ -22,6 +22,7 @@ NL = '\n' # XXX: no longer used by the code below. + NLCRE = re.compile(r'\r\n|\r|\n') + fcre = re.compile(r'^From ', re.MULTILINE) + NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]') ++NEWLINE_WITHOUT_FWSP_BYTES = re.compile(br'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]') + + + +@@ -430,7 +431,16 @@ class BytesGenerator(Generator): + # This is almost the same as the string version, except for handling + # strings with 8bit bytes. + for h, v in msg.raw_items(): +- self._fp.write(self.policy.fold_binary(h, v)) ++ folded = self.policy.fold_binary(h, v) ++ if self.policy.verify_generated_headers: ++ linesep = self.policy.linesep.encode() ++ if not folded.endswith(linesep): ++ raise HeaderWriteError( ++ f'folded header does not end with {linesep!r}: {folded!r}') ++ if NEWLINE_WITHOUT_FWSP_BYTES.search(folded.removesuffix(linesep)): ++ raise HeaderWriteError( ++ f'folded header contains newline: {folded!r}') ++ self._fp.write(folded) + # A blank line always separates headers from body + self.write(self._NL) + +diff --git a/Lib/test/test_email/test_generator.py b/Lib/test/test_email/test_generator.py +index d29400f0ed..a641f871dd 100644 +--- a/Lib/test/test_email/test_generator.py ++++ b/Lib/test/test_email/test_generator.py +@@ -264,7 +264,7 @@ class TestGenerator(TestGeneratorBase, TestEmailBase): + typ = str + + def test_verify_generated_headers(self): +- """gh-121650: by default the generator prevents header injection""" ++ # gh-121650: by default the generator prevents header injection + class LiteralHeader(str): + name = 'Header' + def fold(self, **kwargs): +@@ -285,6 +285,8 @@ class TestGenerator(TestGeneratorBase, TestEmailBase): + + with self.assertRaises(email.errors.HeaderWriteError): + message.as_string() ++ with self.assertRaises(email.errors.HeaderWriteError): ++ message.as_bytes() + + + class TestBytesGenerator(TestGeneratorBase, TestEmailBase): +diff --git a/Lib/test/test_email/test_policy.py b/Lib/test/test_email/test_policy.py +index ff1ddf7d7a..d4a5eb3b59 100644 +--- a/Lib/test/test_email/test_policy.py ++++ b/Lib/test/test_email/test_policy.py +@@ -279,7 +279,7 @@ class PolicyAPITests(unittest.TestCase): + policy.fold("Subject", subject) + + def test_verify_generated_headers(self): +- """Turning protection off allows header injection""" ++ # Turning protection off allows header injection + policy = email.policy.default.clone(verify_generated_headers=False) + for text in ( + 'Header: Value\r\nBad: Injection\r\n', +@@ -302,6 +302,10 @@ class PolicyAPITests(unittest.TestCase): + message.as_string(), + f"{text}\nBody", + ) ++ self.assertEqual( ++ message.as_bytes(), ++ f"{text}\nBody".encode(), ++ ) + + # XXX: Need subclassing tests. + # For adding subclassed objects, make sure the usual rules apply (subclass +diff --git a/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst b/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst +new file mode 100644 +index 0000000000..e6333e7249 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst +@@ -0,0 +1,4 @@ ++:mod:`~email.generator.BytesGenerator` will now refuse to serialize (write) headers ++that are unsafely folded or delimited; see ++:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas ++Bloemsaat and Petr Viktorin in :gh:`121650`). diff --git a/SOURCES/Python-3.9.23.tar.xz.asc b/SOURCES/Python-3.9.23.tar.xz.asc deleted file mode 100644 index 44ac441..0000000 --- a/SOURCES/Python-3.9.23.tar.xz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEE4/8oOcBIslwITevpsmmV4xAlBWgFAmg/SAkACgkQsmmV4xAl -BWjuNA/+Ogt83qY+v8J1o1+YRcJo8w3FUhuOgCALHOd1Q562xldiVyH3Y9uo7sla -j15qz8dFzHPrJddeA993oONnyiXKvsvo8oQ1P41b5BgpifNepCTFVRq/eJA/ZJVV -Dj1g7XwsFo4tbtu9uG51msGaqNFO9OZkwtZG8ucb0njxoA0sO3kIZhbVVG8g2OKM -JLw8dxVmZaQzjCQGBqTMf5cnCwP1TFaaVaJjm1+tVga45G+TIFInwR7kowwPyoWD -7IuZwXu3syPWJP+cMjOxcykMA3HLUBhAV6o9pMvM3JWNdmrwUJRwt41LxY4Q8ZVa -QubnCB9B/uED+PakumiyH2P+gNhAOwzrq7iC8XvxW+/bsJAObTj4cj1WGY7ot+cE -kE7pNoe8NwLiCwt3ENO2QieiHFQvYL9Y+ukQwB2xl+ywsyEwa6RLOvSA5GQs+5r4 -Pv/BgE9nDIzLYVnUMtHic75pmI773pUiHuNXOqdMw4kb61GY5fG+kzVY1HEM1Y8p -krMaEeOEbBNww3Ce0TCzuS/1EhsOB8cB1w9IjtZrtJYCxiVvtdZS8S6F0Y8eJGV2 -xPPcADFv6QKogPrrkbWkwIkT+TKn9s22Dkkr0zdTZ4sTMkGAm08B0kqxbsteI+fJ -I39hHo92mP6W8PuhFJiBkF4ebm61kMwg0mElcueOZiqwW2zRey0= -=Lgxm ------END PGP SIGNATURE----- diff --git a/SOURCES/Python-3.9.25.tar.xz.asc b/SOURCES/Python-3.9.25.tar.xz.asc new file mode 100644 index 0000000..3075c39 --- /dev/null +++ b/SOURCES/Python-3.9.25.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEE4/8oOcBIslwITevpsmmV4xAlBWgFAmkFBpsACgkQsmmV4xAl +BWgwbw//Tx78tZg3/tJ47YDzDCf68XurBPbdgSfmmGTRrveMt6nQbV+c7XKS5MKK +6hP0jt4W8tP6zC/zRPTexqYwetTaM7+ZKuxzwXABXzi+rfmL/L6BtQQpzwK+vesE +hSSkjl4R2FF3YBrTBNqG0ewf5j4Y41yc4V9UHJWXbmQt6sg/nF+lDvG3K3wzP6zV +rs6LsayeO3AXhi7+c0q7d2oYTFhv/RPOGl6/fLy5j1bxNNE1i2yeIfcR9BqjqB9y +Ue1Tea8RGjh3dSq06/8ubpcqf+tlE4cCDkLERqDWSafZnNA5X4eymAQP9urUoH2n +78X8DXkGbKqyJ+3w97S6zqVnZvL2jSOog8R+yvT5snqzJDp+UK0lcbowPILsOGm4 +BE54dQTG5bT+1bUicvQZIbP4vOswZufl8LGmodkW06edSEcylwO8bHWNcY/gC5HO +WcTbqTFyV+FtwAJxsfgkqKcI6xUyYHqeMhqCUvkpHFFMjsinVOBFVbow8fgiJGUV +GIo3kMNPZPirqgl9bhc3F7qvdgVDQsCqnKJ8B1WegdIlKWxXBj3qQB0U4Qbecpdt +2AhVQAmcOu4LzJYtatDp/0tw6KMr8nWGdofrLVJgzQuu6MmhGW+2cJ0e+wUAxw6v +OBjQ0o42ylQKeS8VGP4yFbYv1umeeWHje26z9az3uOVUFaAoptk= +=5qMt +-----END PGP SIGNATURE----- diff --git a/SPECS/python3.9.spec b/SPECS/python3.9.spec index d4c90b2..3ae7988 100644 --- a/SPECS/python3.9.spec +++ b/SPECS/python3.9.spec @@ -13,11 +13,11 @@ URL: https://www.python.org/ # WARNING When rebasing to a new Python version, # remember to update the python3-docs package as well -%global general_version %{pybasever}.23 +%global general_version %{pybasever}.25 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 5%{?dist} License: Python @@ -321,7 +321,7 @@ Patch1: 00001-rpath.patch # See https://bugzilla.redhat.com/show_bug.cgi?id=556092 Patch111: 00111-no-static-lib.patch -# 00189 # d06cf137c00fd3907b436fdb92a8f007a7f2fb50 +# 00189 # 0c6dd5d318a22bbe89e09e1cd5513eaaca549aa5 # Instead of bundled wheels, use our RPM packaged wheels # # We keep them in /usr/share/python-wheels @@ -334,7 +334,7 @@ Patch189: 00189-use-rpm-wheels.patch # When the bundled setuptools/pip wheel is updated, the patch no longer applies cleanly. # In such cases, the patch needs to be amended and the versions updated here: %global pip_version 23.0.1 -%global setuptools_version 58.1.0 +%global setuptools_version 79.0.1 # 00251 # 1b1047c14ff98eae6d355b4aac4df3e388813f62 # Change user install location @@ -438,13 +438,43 @@ Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-par # CVE-2023-52425. Future versions of Expat may be more reactive. Patch422: 00422-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch -# 00467 # -# CVE-2025-8194 +# 00471 # fc5f344f7e15c13dbf41824a1b7a82d92205f79d +# CVE-2025-12084 # -# tarfile now validates archives to ensure member offsets are non-negative. +# * gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146) +# * gh-142754: Ensure that Element & Attr instances have the ownerDocument attribute (GH-142794) +Patch471: 00471-cve-2025-12084.patch + +# 00473 # 7e68b796abe391a467dba42b6641053aac726d67 +# CVE-2026-0865 # -# Upstream issue: https://github.com/python/cpython/issues/130577 -Patch467: 00467-CVE-2025-8194.patch +# gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) +# +# * Add 'test.support' fixture for C0 control characters +# * gh-143916: Reject control characters in wsgiref.headers.Headers +Patch473: 00473-cve-2026-0865.patch + +# 00474 # 837ddca0372fa87ff9cee47142200caa21e77def +# CVE-2025-15366 +# +# gh-143921: Reject control characters in IMAP commands +# +# (cherry-picked from commit 6262704b134db2a4ba12e85ecfbd968534f28b45) +Patch474: 00474-cve-2025-15366.patch + +# 00475 # 00384c03f44af74c955a44637eee0b66f717a487 +# CVE-2025-15367 +# +# gh-143923: Reject control characters in POP3 commands +# +# (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) +Patch475: 00475-cve-2025-15367.patch + +# 00476 # efbfd1798bf8c1a9845546a0ed9193f94661dd1b +# CVE-2026-1299 +# +# gh-144125: email: verify headers are sound in BytesGenerator +Patch476: 00476-cve-2026-1299.patch # (New patches go here ^^^) # @@ -1502,6 +1532,10 @@ CheckPython optimized %dir %{pylibdir}/site-packages/ %dir %{pylibdir}/site-packages/__pycache__/ %{pylibdir}/site-packages/README.txt + +%exclude %{pylibdir}/_sysconfigdata_d_linux_%{platform_triplet}.py +%exclude %{pylibdir}/__pycache__/_sysconfigdata_d_linux_%{platform_triplet}%{bytecode_suffixes} + %{pylibdir}/*.py %dir %{pylibdir}/__pycache__/ %{pylibdir}/__pycache__/*%{bytecode_suffixes} @@ -1827,6 +1861,9 @@ CheckPython optimized %{dynload_dir}/_testinternalcapi.%{SOABI_debug}.so %{dynload_dir}/_testmultiphase.%{SOABI_debug}.so +%{pylibdir}/_sysconfigdata_d_linux_%{platform_triplet}.py +%{pylibdir}/__pycache__/_sysconfigdata_d_linux_%{platform_triplet}%{bytecode_suffixes} + %endif # with debug_build # We put the debug-gdb.py file inside /usr/lib/debug to avoid noise from ldconfig @@ -1850,6 +1887,29 @@ CheckPython optimized # ====================================================== %changelog +* Mon Mar 09 2026 Tomáš Hrnčiar - 3.9.25-5 +- Rebuilding previous fixes for different build target +Related: RHEL-143117, RHEL-143174, RHEL-144897 + +* Wed Feb 25 2026 Tomáš Hrnčiar - 3.9.25-4 +- Security fixes for CVE-2026-0865, CVE-2025-15366, CVE-2025-15367 and CVE-2026-1299 +Resolves: RHEL-143117 +Resolves: RHEL-143174 +Resolves: RHEL-144897 + +* Wed Jan 14 2026 Lumír Balhar - 3.9.25-3 +- Security fix for CVE-2025-12084 +Resolves: RHEL-135897 + +* Mon Nov 10 2025 Tomas Orsava - 3.9.25-2 +- Move _sysconfigdata_d_linux*.py to the debug subpackage + +* Mon Nov 03 2025 Karolina Surma - 3.9.25-1 +- Update to Python 3.9.25 + +* Fri Oct 10 2025 Karolina Surma - 3.9.24-1 +- Update to Python 3.9.24 + * Tue Aug 19 2025 Lumír Balhar - 3.9.23-2 - Security fix for CVE-2025-8194 Resolves: RHEL-106374