Compare commits
1 Commits
imports/c9
...
c9-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5f99f713 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
SOURCES/Python-3.9.23.tar.xz
|
||||
SOURCES/Python-3.9.25.tar.xz
|
||||
|
||||
@ -1 +1 @@
|
||||
73d07237b70b19e4cd530bbc204cccd668ec05d4 SOURCES/Python-3.9.23.tar.xz
|
||||
36c7257ec30dca042679626d0dff79715acd4efb SOURCES/Python-3.9.25.tar.xz
|
||||
|
||||
@ -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/"
|
||||
|
||||
@ -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 <encukou@gmail.com>
|
||||
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
|
||||
|
||||
|
||||
@ -1,215 +0,0 @@
|
||||
From eda136637fc7f056b403e1797a9b0403d6914d9e Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Urieles <aeurielesn@users.noreply.github.com>
|
||||
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 <greg@krypto.org>
|
||||
(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
|
||||
|
||||
140
SOURCES/00471-cve-2025-12084.patch
Normal file
140
SOURCES/00471-cve-2025-12084.patch
Normal file
@ -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 <seth@python.org>
|
||||
Co-authored-by: Petr Viktorin <encukou@gmail.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: 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 <greg@krypto.org>
|
||||
---
|
||||
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.
|
||||
90
SOURCES/00473-cve-2026-0865.patch
Normal file
90
SOURCES/00473-cve-2026-0865.patch
Normal file
@ -0,0 +1,90 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Seth Michael Larson <seth@python.org>
|
||||
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.
|
||||
61
SOURCES/00474-cve-2025-15366.patch
Normal file
61
SOURCES/00474-cve-2025-15366.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Seth Michael Larson <seth@python.org>
|
||||
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<size>\d+)}$'
|
||||
_Untagged_status = br'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?'
|
||||
-
|
||||
+_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.
|
||||
61
SOURCES/00475-cve-2025-15367.patch
Normal file
61
SOURCES/00475-cve-2025-15367.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Seth Michael Larson <seth@python.org>
|
||||
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.
|
||||
108
SOURCES/00476-cve-2026-1299.patch
Normal file
108
SOURCES/00476-cve-2026-1299.patch
Normal file
@ -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 <seth@python.org>
|
||||
Co-authored-by: Denis Ledoux <dle@odoo.com>
|
||||
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`).
|
||||
@ -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-----
|
||||
16
SOURCES/Python-3.9.25.tar.xz.asc
Normal file
16
SOURCES/Python-3.9.25.tar.xz.asc
Normal file
@ -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-----
|
||||
@ -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 <thrnciar@redhat.com> - 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 <thrnciar@redhat.com> - 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 <lbalhar@redhat.com> - 3.9.25-3
|
||||
- Security fix for CVE-2025-12084
|
||||
Resolves: RHEL-135897
|
||||
|
||||
* Mon Nov 10 2025 Tomas Orsava <torsava@redhat.com> - 3.9.25-2
|
||||
- Move _sysconfigdata_d_linux*.py to the debug subpackage
|
||||
|
||||
* Mon Nov 03 2025 Karolina Surma <ksurma@redhat.com> - 3.9.25-1
|
||||
- Update to Python 3.9.25
|
||||
|
||||
* Fri Oct 10 2025 Karolina Surma <ksurma@redhat.com> - 3.9.24-1
|
||||
- Update to Python 3.9.24
|
||||
|
||||
* Tue Aug 19 2025 Lumír Balhar <lbalhar@redhat.com> - 3.9.23-2
|
||||
- Security fix for CVE-2025-8194
|
||||
Resolves: RHEL-106374
|
||||
|
||||
Loading…
Reference in New Issue
Block a user