Compare commits
9 Commits
imports/c9
...
c9-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5f99f713 | ||
| aac3bb2d7d | |||
| cd44f1ad50 | |||
| acd6e96a02 | |||
| 2d9c1663a4 | |||
|
|
818af0d5cf | ||
|
|
2d0264df93 | ||
|
|
194e06e23d | ||
|
|
65fe2eba09 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
SOURCES/Python-3.9.9.tar.xz
|
SOURCES/Python-3.9.25.tar.xz
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
6274e5631c520d75bf1f0a046640fd3996fe99f0 SOURCES/Python-3.9.9.tar.xz
|
36c7257ec30dca042679626d0dff79715acd4efb SOURCES/Python-3.9.25.tar.xz
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
From 12b919396f3fd24521b5ded51e18beb55973f0ff Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
|
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
|
||||||
Date: Wed, 15 Aug 2018 15:36:29 +0200
|
Date: Wed, 15 Aug 2018 15:36:29 +0200
|
||||||
Subject: [PATCH] 00189: Instead of bundled wheels, use our RPM packaged wheels
|
Subject: [PATCH] 00189: Instead of bundled wheels, use our RPM packaged wheels
|
||||||
@ -12,7 +12,7 @@ We might eventually pursuit upstream support, but it's low prio
|
|||||||
1 file changed, 26 insertions(+), 11 deletions(-)
|
1 file changed, 26 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
|
diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py
|
||||||
index 2a140a2624..5bd16a6c59 100644
|
index d61bb089e3..77d7ec5a65 100644
|
||||||
--- a/Lib/ensurepip/__init__.py
|
--- a/Lib/ensurepip/__init__.py
|
||||||
+++ b/Lib/ensurepip/__init__.py
|
+++ b/Lib/ensurepip/__init__.py
|
||||||
@@ -1,3 +1,5 @@
|
@@ -1,3 +1,5 @@
|
||||||
@ -30,8 +30,8 @@ index 2a140a2624..5bd16a6c59 100644
|
|||||||
|
|
||||||
|
|
||||||
__all__ = ["version", "bootstrap"]
|
__all__ = ["version", "bootstrap"]
|
||||||
-_SETUPTOOLS_VERSION = "58.1.0"
|
-_SETUPTOOLS_VERSION = "79.0.1"
|
||||||
-_PIP_VERSION = "21.2.4"
|
-_PIP_VERSION = "23.0.1"
|
||||||
+
|
+
|
||||||
+_WHEEL_DIR = "/usr/share/python-wheels/"
|
+_WHEEL_DIR = "/usr/share/python-wheels/"
|
||||||
+
|
+
|
||||||
@ -73,3 +73,6 @@ index 2a140a2624..5bd16a6c59 100644
|
|||||||
|
|
||||||
additional_paths.append(os.path.join(tmpdir, wheel_name))
|
additional_paths.append(os.path.join(tmpdir, wheel_name))
|
||||||
|
|
||||||
|
--
|
||||||
|
2.35.3
|
||||||
|
|
||||||
|
|||||||
@ -2,41 +2,61 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|||||||
From: Michal Cyprian <m.cyprian@gmail.com>
|
From: Michal Cyprian <m.cyprian@gmail.com>
|
||||||
Date: Mon, 26 Jun 2017 16:32:56 +0200
|
Date: Mon, 26 Jun 2017 16:32:56 +0200
|
||||||
Subject: [PATCH] 00251: Change user install location
|
Subject: [PATCH] 00251: Change user install location
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
Set values of prefix and exec_prefix in distutils install command
|
Set values of prefix and exec_prefix in distutils install command
|
||||||
to /usr/local if executable is /usr/bin/python* and RPM build
|
to /usr/local if executable is /usr/bin/python* and RPM build
|
||||||
is not detected to make pip and distutils install into separate location.
|
is not detected to make pip and distutils install into separate location.
|
||||||
|
|
||||||
Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||||
Downstream only: Awaiting resources to work on upstream PEP
|
Downstream only: Reworked in Fedora 36+/Python 3.10+ to follow https://bugs.python.org/issue43976
|
||||||
|
|
||||||
|
pypa/distutils integration: https://github.com/pypa/distutils/pull/70
|
||||||
|
|
||||||
|
Also set sysconfig._PIP_USE_SYSCONFIG = False, to force pip-upgraded-pip
|
||||||
|
to respect this patched distutils install command.
|
||||||
|
See https://bugzilla.redhat.com/show_bug.cgi?id=2014513
|
||||||
|
|
||||||
|
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
|
||||||
---
|
---
|
||||||
Lib/distutils/command/install.py | 15 +++++++++++++--
|
Lib/distutils/command/install.py | 9 +++++++--
|
||||||
Lib/site.py | 9 ++++++++-
|
Lib/site.py | 9 ++++++++-
|
||||||
2 files changed, 21 insertions(+), 3 deletions(-)
|
Lib/sysconfig.py | 17 +++++++++++++++++
|
||||||
|
3 files changed, 32 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
|
diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py
|
||||||
index aaa300efa9..f8d453912a 100644
|
index aaa300efa9..18f01f10d4 100644
|
||||||
--- a/Lib/distutils/command/install.py
|
--- a/Lib/distutils/command/install.py
|
||||||
+++ b/Lib/distutils/command/install.py
|
+++ b/Lib/distutils/command/install.py
|
||||||
@@ -419,8 +419,19 @@ class install(Command):
|
@@ -3,6 +3,7 @@
|
||||||
|
Implements the Distutils 'install' command."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
+import sysconfig
|
||||||
|
import os
|
||||||
|
|
||||||
|
from distutils import log
|
||||||
|
@@ -142,6 +143,8 @@ class install(Command):
|
||||||
|
|
||||||
|
negative_opt = {'no-compile' : 'compile'}
|
||||||
|
|
||||||
|
+ # Allow Fedora to add components to the prefix
|
||||||
|
+ _prefix_addition = getattr(sysconfig, '_prefix_addition', '')
|
||||||
|
|
||||||
|
def initialize_options(self):
|
||||||
|
"""Initializes options."""
|
||||||
|
@@ -419,8 +422,10 @@ class install(Command):
|
||||||
raise DistutilsOptionError(
|
raise DistutilsOptionError(
|
||||||
"must not supply exec-prefix without prefix")
|
"must not supply exec-prefix without prefix")
|
||||||
|
|
||||||
- self.prefix = os.path.normpath(sys.prefix)
|
- self.prefix = os.path.normpath(sys.prefix)
|
||||||
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
- self.exec_prefix = os.path.normpath(sys.exec_prefix)
|
||||||
+ # self.prefix is set to sys.prefix + /local/
|
+ self.prefix = (
|
||||||
+ # if neither RPM build nor virtual environment is
|
+ os.path.normpath(sys.prefix) + self._prefix_addition)
|
||||||
+ # detected to make pip and distutils install packages
|
+ self.exec_prefix = (
|
||||||
+ # into the separate location.
|
+ os.path.normpath(sys.exec_prefix) + self._prefix_addition)
|
||||||
+ if (not (hasattr(sys, 'real_prefix') or
|
|
||||||
+ sys.prefix != sys.base_prefix) and
|
|
||||||
+ 'RPM_BUILD_ROOT' not in os.environ):
|
|
||||||
+ addition = "/local"
|
|
||||||
+ else:
|
|
||||||
+ addition = ""
|
|
||||||
+
|
|
||||||
+ self.prefix = os.path.normpath(sys.prefix) + addition
|
|
||||||
+ self.exec_prefix = os.path.normpath(sys.exec_prefix) + addition
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if self.exec_prefix is None:
|
if self.exec_prefix is None:
|
||||||
@ -60,3 +80,31 @@ index 9e617afb00..db14f715f9 100644
|
|||||||
for sitedir in getsitepackages(prefixes):
|
for sitedir in getsitepackages(prefixes):
|
||||||
if os.path.isdir(sitedir):
|
if os.path.isdir(sitedir):
|
||||||
addsitedir(sitedir, known_paths)
|
addsitedir(sitedir, known_paths)
|
||||||
|
diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
|
||||||
|
index e3f79bfde5..e124104876 100644
|
||||||
|
--- a/Lib/sysconfig.py
|
||||||
|
+++ b/Lib/sysconfig.py
|
||||||
|
@@ -86,6 +86,23 @@ _INSTALL_SCHEMES = {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
+# Force pip to use distutils paths instead of sysconfig
|
||||||
|
+# https://github.com/pypa/pip/issues/10647
|
||||||
|
+_PIP_USE_SYSCONFIG = False
|
||||||
|
+
|
||||||
|
+# This is used by distutils.command.install in the stdlib
|
||||||
|
+# as well as pypa/distutils (e.g. bundled in setuptools).
|
||||||
|
+# The self.prefix value is set to sys.prefix + /local/
|
||||||
|
+# if neither RPM build nor virtual environment is
|
||||||
|
+# detected to make distutils install packages
|
||||||
|
+# into the separate location.
|
||||||
|
+# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||||
|
+if (not (hasattr(sys, 'real_prefix') or
|
||||||
|
+ sys.prefix != sys.base_prefix) and
|
||||||
|
+ 'RPM_BUILD_ROOT' not in os.environ):
|
||||||
|
+ _prefix_addition = "/local"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
|
||||||
|
'scripts', 'data')
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
251
SOURCES/00397-tarfile-filter.patch
Normal file
251
SOURCES/00397-tarfile-filter.patch
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
From fc3e5ff91495aaf9905bd38ac61db0c3279d17e0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Petr Viktorin <encukou@gmail.com>
|
||||||
|
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.
|
||||||
|
---
|
||||||
|
Lib/tarfile.py | 42 +++++++++++++
|
||||||
|
Lib/test/test_shutil.py | 3 +-
|
||||||
|
Lib/test/test_tarfile.py | 128 ++++++++++++++++++++++++++++++++++++++-
|
||||||
|
3 files changed, 169 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
|
||||||
|
index 209c206..fa3f922 100755
|
||||||
|
--- a/Lib/tarfile.py
|
||||||
|
+++ b/Lib/tarfile.py
|
||||||
|
@@ -72,6 +72,13 @@ __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError",
|
||||||
|
"ENCODING", "USTAR_FORMAT", "GNU_FORMAT", "PAX_FORMAT",
|
||||||
|
"DEFAULT_FORMAT", "open"]
|
||||||
|
|
||||||
|
+# If true, use the safer (but backwards-incompatible) 'tar' extraction filter,
|
||||||
|
+# rather than 'fully_trusted', by default.
|
||||||
|
+# The emitted warning is changed to match.
|
||||||
|
+_RH_SAFER_DEFAULT = True
|
||||||
|
+
|
||||||
|
+# System-wide configuration file
|
||||||
|
+_CONFIG_FILENAME = '/etc/python/tarfile.cfg'
|
||||||
|
|
||||||
|
#---------------------------------------------------------
|
||||||
|
# tar constants
|
||||||
|
@@ -2253,6 +2260,41 @@ class TarFile(object):
|
||||||
|
if filter is None:
|
||||||
|
filter = self.extraction_filter
|
||||||
|
if filter is None:
|
||||||
|
+ name = os.environ.get('PYTHON_TARFILE_EXTRACTION_FILTER')
|
||||||
|
+ if name is None:
|
||||||
|
+ try:
|
||||||
|
+ file = bltn_open(_CONFIG_FILENAME)
|
||||||
|
+ except FileNotFoundError:
|
||||||
|
+ pass
|
||||||
|
+ else:
|
||||||
|
+ import configparser
|
||||||
|
+ conf = configparser.ConfigParser(
|
||||||
|
+ interpolation=None,
|
||||||
|
+ comment_prefixes=('#', ),
|
||||||
|
+ )
|
||||||
|
+ with file:
|
||||||
|
+ conf.read_file(file)
|
||||||
|
+ name = conf.get('tarfile',
|
||||||
|
+ 'PYTHON_TARFILE_EXTRACTION_FILTER',
|
||||||
|
+ fallback='')
|
||||||
|
+ if name:
|
||||||
|
+ try:
|
||||||
|
+ filter = _NAMED_FILTERS[name]
|
||||||
|
+ except KeyError:
|
||||||
|
+ raise ValueError(f"filter {filter!r} not found") from None
|
||||||
|
+ self.extraction_filter = filter
|
||||||
|
+ return filter
|
||||||
|
+ if _RH_SAFER_DEFAULT:
|
||||||
|
+ warnings.warn(
|
||||||
|
+ 'The default behavior of tarfile extraction has been '
|
||||||
|
+ + 'changed to disallow common exploits '
|
||||||
|
+ + '(including CVE-2007-4559). '
|
||||||
|
+ + 'By default, absolute/parent paths are disallowed '
|
||||||
|
+ + 'and some mode bits are cleared. '
|
||||||
|
+ + 'See https://access.redhat.com/articles/7004769 '
|
||||||
|
+ + 'for more details.',
|
||||||
|
+ RuntimeWarning)
|
||||||
|
+ return tar_filter
|
||||||
|
return fully_trusted_filter
|
||||||
|
if isinstance(filter, str):
|
||||||
|
raise TypeError(
|
||||||
|
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
|
||||||
|
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):
|
||||||
|
def check_unpack_tarball(self, format):
|
||||||
|
self.check_unpack_archive(format, filter='fully_trusted')
|
||||||
|
self.check_unpack_archive(format, filter='data')
|
||||||
|
- with warnings_helper.check_no_warnings(self):
|
||||||
|
+ with warnings_helper.check_warnings(
|
||||||
|
+ ('.*CVE-2007-4559', RuntimeWarning)):
|
||||||
|
self.check_unpack_archive(format)
|
||||||
|
|
||||||
|
def test_unpack_archive_tar(self):
|
||||||
|
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
|
||||||
|
index 17d2239..8b9aea2 100644
|
||||||
|
--- a/Lib/test/test_tarfile.py
|
||||||
|
+++ b/Lib/test/test_tarfile.py
|
||||||
|
@@ -3,7 +3,7 @@ import sys
|
||||||
|
import os
|
||||||
|
import io
|
||||||
|
from hashlib import sha256
|
||||||
|
-from contextlib import contextmanager
|
||||||
|
+from contextlib import contextmanager, ExitStack
|
||||||
|
from random import Random
|
||||||
|
import pathlib
|
||||||
|
import shutil
|
||||||
|
@@ -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
|
||||||
|
- tar.extractall(cls.control_dir, filter=cls.extraction_filter)
|
||||||
|
+ with ExitStack() as cm:
|
||||||
|
+ if cls.extraction_filter is None:
|
||||||
|
+ cm.enter_context(warnings.catch_warnings())
|
||||||
|
+ warnings.simplefilter(action="ignore", category=RuntimeWarning)
|
||||||
|
+ tar.extractall(cls.control_dir, filter=cls.extraction_filter)
|
||||||
|
tar.close()
|
||||||
|
cls.control_paths = set(
|
||||||
|
p.relative_to(cls.control_dir)
|
||||||
|
@@ -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')
|
||||||
|
- with warnings_helper.check_no_warnings(self):
|
||||||
|
+ with warnings_helper.check_warnings(
|
||||||
|
+ ('.*CVE-2007-4559', RuntimeWarning)):
|
||||||
|
with self.check_context(arc.open(), None):
|
||||||
|
self.expect_file('foo')
|
||||||
|
|
||||||
|
@@ -4390,6 +4395,123 @@ class OffsetValidationTests(unittest.TestCase):
|
||||||
|
self.assertEqual(members[0].offset, expected_offset)
|
||||||
|
|
||||||
|
|
||||||
|
+ @contextmanager
|
||||||
|
+ def rh_config_context(self, config_lines=None):
|
||||||
|
+ """Set up for testing various ways of overriding the default filter
|
||||||
|
+
|
||||||
|
+ return a triple with:
|
||||||
|
+ - temporary directory
|
||||||
|
+ - EnvironmentVarGuard()
|
||||||
|
+ - a test archive for use with check_* methods below
|
||||||
|
+
|
||||||
|
+ If config_lines is given, write them to the config file. Otherwise
|
||||||
|
+ the config file is missing.
|
||||||
|
+ """
|
||||||
|
+ tempdir = pathlib.Path(TEMPDIR) / 'tmp'
|
||||||
|
+ configfile = tempdir / 'tarfile.cfg'
|
||||||
|
+ with ArchiveMaker() as arc:
|
||||||
|
+ arc.add('good')
|
||||||
|
+ arc.add('ugly', symlink_to='/etc/passwd')
|
||||||
|
+ arc.add('../bad')
|
||||||
|
+ with (
|
||||||
|
+ support.temp_dir(tempdir),
|
||||||
|
+ support.swap_attr(tarfile, '_CONFIG_FILENAME', str(configfile)),
|
||||||
|
+ support.EnvironmentVarGuard() as env,
|
||||||
|
+ arc.open() as tar,
|
||||||
|
+ ):
|
||||||
|
+ if config_lines is not None:
|
||||||
|
+ with configfile.open('w') as f:
|
||||||
|
+ for line in config_lines:
|
||||||
|
+ print(line, file=f)
|
||||||
|
+ yield tempdir, env, tar
|
||||||
|
+
|
||||||
|
+ def check_rh_default_behavior(self, tar, tempdir):
|
||||||
|
+ """Check RH default: warn and refuse to extract dangerous files."""
|
||||||
|
+ with (
|
||||||
|
+ warnings_helper.check_warnings(
|
||||||
|
+ ('.*CVE-2007-4559', RuntimeWarning)),
|
||||||
|
+ self.assertRaises(tarfile.OutsideDestinationError),
|
||||||
|
+ ):
|
||||||
|
+ tar.extractall(tempdir / 'outdir')
|
||||||
|
+
|
||||||
|
+ def check_trusted_default(self, tar, tempdir):
|
||||||
|
+ """Check 'fully_trusted' is configured as the default filter."""
|
||||||
|
+ with (
|
||||||
|
+ warnings_helper.check_no_warnings(self),
|
||||||
|
+ ):
|
||||||
|
+ tar.extractall(tempdir / 'outdir')
|
||||||
|
+ self.assertTrue((tempdir / 'outdir/good').exists())
|
||||||
|
+ self.assertEqual((tempdir / 'outdir/ugly').readlink(),
|
||||||
|
+ pathlib.Path('/etc/passwd'))
|
||||||
|
+ self.assertTrue((tempdir / 'bad').exists())
|
||||||
|
+
|
||||||
|
+ def test_rh_default_no_conf(self):
|
||||||
|
+ with self.rh_config_context() as (tempdir, env, tar):
|
||||||
|
+ self.check_rh_default_behavior(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_rh_default_from_file(self):
|
||||||
|
+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=fully_trusted']
|
||||||
|
+ with self.rh_config_context(lines) as (tempdir, env, tar):
|
||||||
|
+ self.check_trusted_default(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_rh_empty_config_file(self):
|
||||||
|
+ """Empty config file -> default behavior"""
|
||||||
|
+ lines = []
|
||||||
|
+ with self.rh_config_context(lines) as (tempdir, env, tar):
|
||||||
|
+ self.check_rh_default_behavior(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_empty_config_section(self):
|
||||||
|
+ """Empty section in config file -> default behavior"""
|
||||||
|
+ lines = ['[tarfile]']
|
||||||
|
+ with self.rh_config_context(lines) as (tempdir, env, tar):
|
||||||
|
+ self.check_rh_default_behavior(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_rh_default_empty_config_option(self):
|
||||||
|
+ """Empty option value in config file -> default behavior"""
|
||||||
|
+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=']
|
||||||
|
+ with self.rh_config_context(lines) as (tempdir, env, tar):
|
||||||
|
+ self.check_rh_default_behavior(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_bad_config_option(self):
|
||||||
|
+ """Bad option value in config file -> ValueError"""
|
||||||
|
+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=unknown!']
|
||||||
|
+ with self.rh_config_context(lines) as (tempdir, env, tar):
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ tar.extractall(tempdir / 'outdir')
|
||||||
|
+
|
||||||
|
+ def test_default_from_envvar(self):
|
||||||
|
+ with self.rh_config_context() as (tempdir, env, tar):
|
||||||
|
+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'fully_trusted'
|
||||||
|
+ self.check_trusted_default(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_empty_envvar(self):
|
||||||
|
+ """Empty env variable -> default behavior"""
|
||||||
|
+ with self.rh_config_context() as (tempdir, env, tar):
|
||||||
|
+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = ''
|
||||||
|
+ self.check_rh_default_behavior(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_bad_envvar(self):
|
||||||
|
+ with self.rh_config_context() as (tempdir, env, tar):
|
||||||
|
+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'unknown!'
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ tar.extractall(tempdir / 'outdir')
|
||||||
|
+
|
||||||
|
+ def test_envvar_overrides_file(self):
|
||||||
|
+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=data']
|
||||||
|
+ with self.rh_config_context(lines) as (tempdir, env, tar):
|
||||||
|
+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'fully_trusted'
|
||||||
|
+ self.check_trusted_default(tar, tempdir)
|
||||||
|
+
|
||||||
|
+ def test_monkeypatch_overrides_envvar(self):
|
||||||
|
+ with self.rh_config_context(None) as (tempdir, env, tar):
|
||||||
|
+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'data'
|
||||||
|
+ with support.swap_attr(
|
||||||
|
+ tarfile.TarFile, 'extraction_filter',
|
||||||
|
+ staticmethod(tarfile.fully_trusted_filter)
|
||||||
|
+ ):
|
||||||
|
+ self.check_trusted_default(tar, tempdir)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def setUpModule():
|
||||||
|
support.unlink(TEMPDIR)
|
||||||
|
os.makedirs(TEMPDIR)
|
||||||
|
--
|
||||||
|
2.51.1
|
||||||
|
|
||||||
@ -0,0 +1,248 @@
|
|||||||
|
From 4df4fad359c280f2328b98ea9b4414f244624a58 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lumir Balhar <lbalhar@redhat.com>
|
||||||
|
Date: Mon, 18 Dec 2023 20:15:33 +0100
|
||||||
|
Subject: [PATCH] Make it possible to disable strict parsing in email module
|
||||||
|
|
||||||
|
---
|
||||||
|
Doc/library/email.utils.rst | 26 +++++++++++
|
||||||
|
Lib/email/utils.py | 54 ++++++++++++++++++++++-
|
||||||
|
Lib/test/test_email/test_email.py | 72 ++++++++++++++++++++++++++++++-
|
||||||
|
3 files changed, 149 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst
|
||||||
|
index d1e1898591..7aef773b5f 100644
|
||||||
|
--- a/Doc/library/email.utils.rst
|
||||||
|
+++ b/Doc/library/email.utils.rst
|
||||||
|
@@ -69,6 +69,19 @@ of the new API.
|
||||||
|
|
||||||
|
If *strict* is true, use a strict parser which rejects malformed inputs.
|
||||||
|
|
||||||
|
+ The default setting for *strict* is set to ``True``, but you can override
|
||||||
|
+ it by setting the environment variable ``PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING``
|
||||||
|
+ to non-empty string.
|
||||||
|
+
|
||||||
|
+ Additionally, you can permanently set the default value for *strict* to
|
||||||
|
+ ``False`` by creating the configuration file ``/etc/python/email.cfg``
|
||||||
|
+ with the following content:
|
||||||
|
+
|
||||||
|
+ .. code-block:: ini
|
||||||
|
+
|
||||||
|
+ [email_addr_parsing]
|
||||||
|
+ PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING = true
|
||||||
|
+
|
||||||
|
.. versionchanged:: 3.9.20
|
||||||
|
Add *strict* optional parameter and reject malformed inputs by default.
|
||||||
|
|
||||||
|
@@ -97,6 +110,19 @@ of the new API.
|
||||||
|
|
||||||
|
If *strict* is true, use a strict parser which rejects malformed inputs.
|
||||||
|
|
||||||
|
+ The default setting for *strict* is set to ``True``, but you can override
|
||||||
|
+ it by setting the environment variable ``PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING``
|
||||||
|
+ to non-empty string.
|
||||||
|
+
|
||||||
|
+ Additionally, you can permanently set the default value for *strict* to
|
||||||
|
+ ``False`` by creating the configuration file ``/etc/python/email.cfg``
|
||||||
|
+ with the following content:
|
||||||
|
+
|
||||||
|
+ .. code-block:: ini
|
||||||
|
+
|
||||||
|
+ [email_addr_parsing]
|
||||||
|
+ PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING = true
|
||||||
|
+
|
||||||
|
Here's a simple example that gets all the recipients of a message::
|
||||||
|
|
||||||
|
from email.utils import getaddresses
|
||||||
|
diff --git a/Lib/email/utils.py b/Lib/email/utils.py
|
||||||
|
index f83b7e5d7e..b8e90ceb8e 100644
|
||||||
|
--- a/Lib/email/utils.py
|
||||||
|
+++ b/Lib/email/utils.py
|
||||||
|
@@ -48,6 +48,46 @@ TICK = "'"
|
||||||
|
specialsre = re.compile(r'[][\\()<>@,:;".]')
|
||||||
|
escapesre = re.compile(r'[\\"]')
|
||||||
|
|
||||||
|
+_EMAIL_CONFIG_FILE = "/etc/python/email.cfg"
|
||||||
|
+_cached_strict_addr_parsing = None
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _use_strict_email_parsing():
|
||||||
|
+ """"Cache implementation for _cached_strict_addr_parsing"""
|
||||||
|
+ global _cached_strict_addr_parsing
|
||||||
|
+ if _cached_strict_addr_parsing is None:
|
||||||
|
+ _cached_strict_addr_parsing = _use_strict_email_parsing_impl()
|
||||||
|
+ return _cached_strict_addr_parsing
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _use_strict_email_parsing_impl():
|
||||||
|
+ """Returns True if strict email parsing is not disabled by
|
||||||
|
+ config file or env variable.
|
||||||
|
+ """
|
||||||
|
+ disabled = bool(os.environ.get("PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING"))
|
||||||
|
+ if disabled:
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+ try:
|
||||||
|
+ file = open(_EMAIL_CONFIG_FILE)
|
||||||
|
+ except FileNotFoundError:
|
||||||
|
+ pass
|
||||||
|
+ else:
|
||||||
|
+ with file:
|
||||||
|
+ import configparser
|
||||||
|
+ config = configparser.ConfigParser(
|
||||||
|
+ interpolation=None,
|
||||||
|
+ comment_prefixes=('#', ),
|
||||||
|
+
|
||||||
|
+ )
|
||||||
|
+ config.read_file(file)
|
||||||
|
+ disabled = config.getboolean('email_addr_parsing', "PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING", fallback=None)
|
||||||
|
+
|
||||||
|
+ if disabled:
|
||||||
|
+ return False
|
||||||
|
+
|
||||||
|
+ return True
|
||||||
|
+
|
||||||
|
|
||||||
|
def _has_surrogates(s):
|
||||||
|
"""Return True if s contains surrogate-escaped binary data."""
|
||||||
|
@@ -149,7 +189,7 @@ def _strip_quoted_realnames(addr):
|
||||||
|
|
||||||
|
supports_strict_parsing = True
|
||||||
|
|
||||||
|
-def getaddresses(fieldvalues, *, strict=True):
|
||||||
|
+def getaddresses(fieldvalues, *, strict=None):
|
||||||
|
"""Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue.
|
||||||
|
|
||||||
|
When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in
|
||||||
|
@@ -158,6 +198,11 @@ def getaddresses(fieldvalues, *, strict=True):
|
||||||
|
If strict is true, use a strict parser which rejects malformed inputs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
+ # If default is used, it's True unless disabled
|
||||||
|
+ # by env variable or config file.
|
||||||
|
+ if strict == None:
|
||||||
|
+ strict = _use_strict_email_parsing()
|
||||||
|
+
|
||||||
|
# If strict is true, if the resulting list of parsed addresses is greater
|
||||||
|
# than the number of fieldvalues in the input list, a parsing error has
|
||||||
|
# occurred and consequently a list containing a single empty 2-tuple [('',
|
||||||
|
@@ -330,7 +375,7 @@ def parsedate_to_datetime(data):
|
||||||
|
tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
|
||||||
|
|
||||||
|
|
||||||
|
-def parseaddr(addr, *, strict=True):
|
||||||
|
+def parseaddr(addr, *, strict=None):
|
||||||
|
"""
|
||||||
|
Parse addr into its constituent realname and email address parts.
|
||||||
|
|
||||||
|
@@ -339,6 +384,11 @@ def parseaddr(addr, *, strict=True):
|
||||||
|
|
||||||
|
If strict is True, use a strict parser which rejects malformed inputs.
|
||||||
|
"""
|
||||||
|
+ # If default is used, it's True unless disabled
|
||||||
|
+ # by env variable or config file.
|
||||||
|
+ if strict == None:
|
||||||
|
+ strict = _use_strict_email_parsing()
|
||||||
|
+
|
||||||
|
if not strict:
|
||||||
|
addrs = _AddressList(addr).addresslist
|
||||||
|
if not addrs:
|
||||||
|
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
|
||||||
|
index ce36efc1b1..05ea201b68 100644
|
||||||
|
--- a/Lib/test/test_email/test_email.py
|
||||||
|
+++ b/Lib/test/test_email/test_email.py
|
||||||
|
@@ -7,6 +7,9 @@ import time
|
||||||
|
import base64
|
||||||
|
import unittest
|
||||||
|
import textwrap
|
||||||
|
+import contextlib
|
||||||
|
+import tempfile
|
||||||
|
+import os
|
||||||
|
|
||||||
|
from io import StringIO, BytesIO
|
||||||
|
from itertools import chain
|
||||||
|
@@ -41,7 +44,7 @@ from email import iterators
|
||||||
|
from email import base64mime
|
||||||
|
from email import quoprimime
|
||||||
|
|
||||||
|
-from test.support import unlink, start_threads
|
||||||
|
+from test.support import unlink, start_threads, EnvironmentVarGuard, swap_attr
|
||||||
|
from test.test_email import openfile, TestEmailBase
|
||||||
|
|
||||||
|
# These imports are documented to work, but we are testing them using a
|
||||||
|
@@ -3313,6 +3316,73 @@ Foo
|
||||||
|
# Test email.utils.supports_strict_parsing attribute
|
||||||
|
self.assertEqual(email.utils.supports_strict_parsing, True)
|
||||||
|
|
||||||
|
+ def test_parsing_errors_strict_set_via_env_var(self):
|
||||||
|
+ address = 'alice@example.org )Alice('
|
||||||
|
+ empty = ('', '')
|
||||||
|
+
|
||||||
|
+ # Reset cached default value to make the function
|
||||||
|
+ # reload the config file provided below.
|
||||||
|
+ utils._cached_strict_addr_parsing = None
|
||||||
|
+
|
||||||
|
+ # Strict disabled via env variable, old behavior expected
|
||||||
|
+ with EnvironmentVarGuard() as environ:
|
||||||
|
+ environ["PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING"] = "1"
|
||||||
|
+
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]),
|
||||||
|
+ [('', 'alice@example.org'), ('', ''), ('', 'Alice')])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), ('', address))
|
||||||
|
+
|
||||||
|
+ # Clear cache again
|
||||||
|
+ utils._cached_strict_addr_parsing = None
|
||||||
|
+
|
||||||
|
+ # Default strict=True, empty result expected
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]), [empty])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), empty)
|
||||||
|
+
|
||||||
|
+ # Clear cache again
|
||||||
|
+ utils._cached_strict_addr_parsing = None
|
||||||
|
+
|
||||||
|
+ # Empty string in env variable = strict parsing enabled (default)
|
||||||
|
+ with EnvironmentVarGuard() as environ:
|
||||||
|
+ environ["PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING"] = ""
|
||||||
|
+
|
||||||
|
+ # Default strict=True, empty result expected
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]), [empty])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), empty)
|
||||||
|
+
|
||||||
|
+ @contextlib.contextmanager
|
||||||
|
+ def _email_strict_parsing_conf(self):
|
||||||
|
+ """Context for the given email strict parsing configured in config file"""
|
||||||
|
+ with tempfile.TemporaryDirectory() as tmpdirname:
|
||||||
|
+ filename = os.path.join(tmpdirname, 'conf.cfg')
|
||||||
|
+ with swap_attr(utils, "_EMAIL_CONFIG_FILE", filename):
|
||||||
|
+ with open(filename, 'w') as file:
|
||||||
|
+ file.write('[email_addr_parsing]\n')
|
||||||
|
+ file.write('PYTHON_EMAIL_DISABLE_STRICT_ADDR_PARSING = true')
|
||||||
|
+ utils._EMAIL_CONFIG_FILE = filename
|
||||||
|
+ yield
|
||||||
|
+
|
||||||
|
+ def test_parsing_errors_strict_disabled_via_config_file(self):
|
||||||
|
+ address = 'alice@example.org )Alice('
|
||||||
|
+ empty = ('', '')
|
||||||
|
+
|
||||||
|
+ # Reset cached default value to make the function
|
||||||
|
+ # reload the config file provided below.
|
||||||
|
+ utils._cached_strict_addr_parsing = None
|
||||||
|
+
|
||||||
|
+ # Strict disabled via config file, old results expected
|
||||||
|
+ with self._email_strict_parsing_conf():
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]),
|
||||||
|
+ [('', 'alice@example.org'), ('', ''), ('', 'Alice')])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), ('', address))
|
||||||
|
+
|
||||||
|
+ # Clear cache again
|
||||||
|
+ utils._cached_strict_addr_parsing = None
|
||||||
|
+
|
||||||
|
+ # Default strict=True, empty result expected
|
||||||
|
+ self.assertEqual(utils.getaddresses([address]), [empty])
|
||||||
|
+ self.assertEqual(utils.parseaddr([address]), empty)
|
||||||
|
+
|
||||||
|
def test_getaddresses_nasty(self):
|
||||||
|
for addresses, expected in (
|
||||||
|
(['"Sürname, Firstname" <to@example.com>'],
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
From 60d40d7095983e0bc23a103b2050adc519dc7fe3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Lumir Balhar <lbalhar@redhat.com>
|
||||||
|
Date: Fri, 3 May 2024 14:17:48 +0200
|
||||||
|
Subject: [PATCH] Expect failures in tests not working properly with expat with
|
||||||
|
a fixed CVE in RHEL
|
||||||
|
|
||||||
|
---
|
||||||
|
Lib/test/test_pyexpat.py | 1 +
|
||||||
|
Lib/test/test_sax.py | 1 +
|
||||||
|
Lib/test/test_xml_etree.py | 3 +++
|
||||||
|
3 files changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py
|
||||||
|
index 43cbd27..27b1502 100644
|
||||||
|
--- a/Lib/test/test_pyexpat.py
|
||||||
|
+++ b/Lib/test/test_pyexpat.py
|
||||||
|
@@ -793,6 +793,7 @@ class ReparseDeferralTest(unittest.TestCase):
|
||||||
|
|
||||||
|
self.assertEqual(started, ['doc'])
|
||||||
|
|
||||||
|
+ @unittest.expectedFailure
|
||||||
|
def test_reparse_deferral_disabled(self):
|
||||||
|
started = []
|
||||||
|
|
||||||
|
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
|
||||||
|
index 9b3014a..646c92d 100644
|
||||||
|
--- a/Lib/test/test_sax.py
|
||||||
|
+++ b/Lib/test/test_sax.py
|
||||||
|
@@ -1240,6 +1240,7 @@ class ExpatReaderTest(XmlTestBase):
|
||||||
|
|
||||||
|
self.assertEqual(result.getvalue(), start + b"<doc></doc>")
|
||||||
|
|
||||||
|
+ @unittest.expectedFailure
|
||||||
|
def test_flush_reparse_deferral_disabled(self):
|
||||||
|
result = BytesIO()
|
||||||
|
xmlgen = XMLGenerator(result)
|
||||||
|
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
|
||||||
|
index 9c382d1..62f2871 100644
|
||||||
|
--- a/Lib/test/test_xml_etree.py
|
||||||
|
+++ b/Lib/test/test_xml_etree.py
|
||||||
|
@@ -1424,9 +1424,11 @@ class XMLPullParserTest(unittest.TestCase):
|
||||||
|
self.assert_event_tags(parser, [('end', 'root')])
|
||||||
|
self.assertIsNone(parser.close())
|
||||||
|
|
||||||
|
+ @unittest.expectedFailure
|
||||||
|
def test_simple_xml_chunk_1(self):
|
||||||
|
self.test_simple_xml(chunk_size=1, flush=True)
|
||||||
|
|
||||||
|
+ @unittest.expectedFailure
|
||||||
|
def test_simple_xml_chunk_5(self):
|
||||||
|
self.test_simple_xml(chunk_size=5, flush=True)
|
||||||
|
|
||||||
|
@@ -1651,6 +1653,7 @@ class XMLPullParserTest(unittest.TestCase):
|
||||||
|
|
||||||
|
self.assert_event_tags(parser, [('end', 'doc')])
|
||||||
|
|
||||||
|
+ @unittest.expectedFailure
|
||||||
|
def test_flush_reparse_deferral_disabled(self):
|
||||||
|
parser = ET.XMLPullParser(events=('start', 'end'))
|
||||||
|
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
||||||
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`).
|
||||||
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-----
|
||||||
@ -1,16 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQIzBAABCgAdFiEE4/8oOcBIslwITevpsmmV4xAlBWgFAmGSq04ACgkQsmmV4xAl
|
|
||||||
BWjtXQ/8CggiE692fd0jq3sVMNdAarUwWPWTVblm3H0zkwrpkrLAOTZfb+6UMini
|
|
||||||
XbXgFBIAERLffO5XHumJgXKR9pkJmYxQ5gjz+9YA5hBswQzj6x6nFqANYj3Jes7N
|
|
||||||
GUTohgVgmhfTW8EsJwE+bfRuJfpQaWDS1YHErjvfH+iywpJdagNGoHlxjoFFY4LQ
|
|
||||||
pOxO9fe6WqCCqGcGoniyRrGOpoyo59eMezVc9bCOeuvsEhOxcxAJq8bEMrphL0AJ
|
|
||||||
EOAsb5AZYsQFZhxbdN//f5CPMJ1eskqYN0ho1LGhL/z0JcRUDpAb4h5YQHcCgQN+
|
|
||||||
rNM6keTfFtNEa19ByW74f1fJJw/VgqBHNm6AVnvw9WOJvhlwSei0xeZHZtSL5VtH
|
|
||||||
WsJtZuhYqRWCrokjt2HOVD4b8vvAegaEqEPR+SFPBqJJbiHJ/LQTOv+fweQnyo+F
|
|
||||||
EXKof0ZXbax7Q/ADIVhd2y3C0hYrpzRKVEk1u643ns0V+wZ2VuilL/k5aB/LaOoy
|
|
||||||
Z9O2WoxSw0SMm0etegVyefT5+gj5l/8euXwKWqxKFPhue7pWngwzMPzjkMDcvfYb
|
|
||||||
4o21d9vbTFvGAHJ5SCqHPLy5iIf40pfLLZreEXtSMLM1mGMlfGnt270UasUIIxWE
|
|
||||||
TxHYHthQX0M2hMW77dc5hcVcRrUNKmf8P7XbnDjc61eSlRgTJaE=
|
|
||||||
=2zA6
|
|
||||||
-----END PGP SIGNATURE-----
|
|
||||||
@ -13,11 +13,11 @@ URL: https://www.python.org/
|
|||||||
|
|
||||||
# WARNING When rebasing to a new Python version,
|
# WARNING When rebasing to a new Python version,
|
||||||
# remember to update the python3-docs package as well
|
# remember to update the python3-docs package as well
|
||||||
%global general_version %{pybasever}.9
|
%global general_version %{pybasever}.25
|
||||||
#global prerel ...
|
#global prerel ...
|
||||||
%global upstream_version %{general_version}%{?prerel}
|
%global upstream_version %{general_version}%{?prerel}
|
||||||
Version: %{general_version}%{?prerel:~%{prerel}}
|
Version: %{general_version}%{?prerel:~%{prerel}}
|
||||||
Release: 2%{?dist}
|
Release: 5%{?dist}
|
||||||
License: Python
|
License: Python
|
||||||
|
|
||||||
|
|
||||||
@ -195,6 +195,13 @@ License: Python
|
|||||||
%global py_INSTSONAME_optimized libpython%{LDVERSION_optimized}.so.%{py_SOVERSION}
|
%global py_INSTSONAME_optimized libpython%{LDVERSION_optimized}.so.%{py_SOVERSION}
|
||||||
%global py_INSTSONAME_debug libpython%{LDVERSION_debug}.so.%{py_SOVERSION}
|
%global py_INSTSONAME_debug libpython%{LDVERSION_debug}.so.%{py_SOVERSION}
|
||||||
|
|
||||||
|
# The -O flag for the compiler, optimized builds
|
||||||
|
# https://fedoraproject.org/wiki/Changes/Python_built_with_gcc_O3
|
||||||
|
%global optflags_optimized -O3
|
||||||
|
# The -O flag for the compiler, debug builds
|
||||||
|
# -Wno-cpp avoids some warnings with -O0
|
||||||
|
%global optflags_debug -O0 -Wno-cpp
|
||||||
|
|
||||||
# Disable automatic bytecompilation. The python3 binary is not yet be
|
# Disable automatic bytecompilation. The python3 binary is not yet be
|
||||||
# available in /usr/bin when Python is built. Also, the bytecompilation fails
|
# available in /usr/bin when Python is built. Also, the bytecompilation fails
|
||||||
# on files that test invalid syntax.
|
# on files that test invalid syntax.
|
||||||
@ -262,6 +269,7 @@ BuildRequires: valgrind-devel
|
|||||||
BuildRequires: xz-devel
|
BuildRequires: xz-devel
|
||||||
BuildRequires: zlib-devel
|
BuildRequires: zlib-devel
|
||||||
|
|
||||||
|
BuildRequires: systemtap-sdt-devel
|
||||||
BuildRequires: /usr/bin/dtrace
|
BuildRequires: /usr/bin/dtrace
|
||||||
|
|
||||||
# workaround http://bugs.python.org/issue19804 (test_uuid requires ifconfig)
|
# workaround http://bugs.python.org/issue19804 (test_uuid requires ifconfig)
|
||||||
@ -313,7 +321,7 @@ Patch1: 00001-rpath.patch
|
|||||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=556092
|
# See https://bugzilla.redhat.com/show_bug.cgi?id=556092
|
||||||
Patch111: 00111-no-static-lib.patch
|
Patch111: 00111-no-static-lib.patch
|
||||||
|
|
||||||
# 00189 # d06cf137c00fd3907b436fdb92a8f007a7f2fb50
|
# 00189 # 0c6dd5d318a22bbe89e09e1cd5513eaaca549aa5
|
||||||
# Instead of bundled wheels, use our RPM packaged wheels
|
# Instead of bundled wheels, use our RPM packaged wheels
|
||||||
#
|
#
|
||||||
# We keep them in /usr/share/python-wheels
|
# We keep them in /usr/share/python-wheels
|
||||||
@ -325,10 +333,10 @@ Patch189: 00189-use-rpm-wheels.patch
|
|||||||
# The versions are written in Lib/ensurepip/__init__.py, this patch removes them.
|
# The versions are written in Lib/ensurepip/__init__.py, this patch removes them.
|
||||||
# When the bundled setuptools/pip wheel is updated, the patch no longer applies cleanly.
|
# 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:
|
# In such cases, the patch needs to be amended and the versions updated here:
|
||||||
%global pip_version 21.2.4
|
%global pip_version 23.0.1
|
||||||
%global setuptools_version 58.1.0
|
%global setuptools_version 79.0.1
|
||||||
|
|
||||||
# 00251 # 2eabd04356402d488060bc8fe316ad13fc8a3356
|
# 00251 # 1b1047c14ff98eae6d355b4aac4df3e388813f62
|
||||||
# Change user install location
|
# Change user install location
|
||||||
#
|
#
|
||||||
# Set values of prefix and exec_prefix in distutils install command
|
# Set values of prefix and exec_prefix in distutils install command
|
||||||
@ -336,7 +344,13 @@ Patch189: 00189-use-rpm-wheels.patch
|
|||||||
# is not detected to make pip and distutils install into separate location.
|
# is not detected to make pip and distutils install into separate location.
|
||||||
#
|
#
|
||||||
# Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
# Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe
|
||||||
# Downstream only: Awaiting resources to work on upstream PEP
|
# Downstream only: Reworked in Fedora 36+/Python 3.10+ to follow https://bugs.python.org/issue43976
|
||||||
|
#
|
||||||
|
# pypa/distutils integration: https://github.com/pypa/distutils/pull/70
|
||||||
|
#
|
||||||
|
# Also set sysconfig._PIP_USE_SYSCONFIG = False, to force pip-upgraded-pip
|
||||||
|
# to respect this patched distutils install command.
|
||||||
|
# See https://bugzilla.redhat.com/show_bug.cgi?id=2014513
|
||||||
Patch251: 00251-change-user-install-location.patch
|
Patch251: 00251-change-user-install-location.patch
|
||||||
|
|
||||||
# 00328 # 367fdcb5a075f083aea83ac174999272a8faf75c
|
# 00328 # 367fdcb5a075f083aea83ac174999272a8faf75c
|
||||||
@ -363,8 +377,9 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch
|
|||||||
# - In FIPS mode, the blake2 hashes use OpenSSL wrappers
|
# - In FIPS mode, the blake2 hashes use OpenSSL wrappers
|
||||||
# and do not offer extended functionality (keys, tree hashing, custom digest size)
|
# and do not offer extended functionality (keys, tree hashing, custom digest size)
|
||||||
#
|
#
|
||||||
# - The patch, in its current state, is in a preliminary form to set the groundwork
|
# - In FIPS mode, hmac.HMAC can only be instantiated with an OpenSSL wrapper
|
||||||
# for refining Python's FIPS compatibility until OpenSSL is FIPS ready.
|
# or a string with OpenSSL hash name as the "digestmod" argument.
|
||||||
|
# The argument must be specified (instead of defaulting to ‘md5’).
|
||||||
Patch329: 00329-fips.patch
|
Patch329: 00329-fips.patch
|
||||||
|
|
||||||
# 00353 # ab4cc97b643cfe99f567e3a03e5617b507183771
|
# 00353 # ab4cc97b643cfe99f567e3a03e5617b507183771
|
||||||
@ -392,6 +407,75 @@ Patch329: 00329-fips.patch
|
|||||||
# a nightmare because it's basically a binary file.
|
# a nightmare because it's basically a binary file.
|
||||||
Patch353: 00353-architecture-names-upstream-downstream.patch
|
Patch353: 00353-architecture-names-upstream-downstream.patch
|
||||||
|
|
||||||
|
# 00397 #
|
||||||
|
# Add filters for tarfile extraction (CVE-2007-4559, PEP-706)
|
||||||
|
# First patch fixes determination of symlink targets, which were treated
|
||||||
|
# as relative to the root of the archive,
|
||||||
|
# rather than the directory containing the symlink.
|
||||||
|
# Not yet upstream as of this writing.
|
||||||
|
# The second patch is Red Hat configuration, see KB for documentation:
|
||||||
|
# - https://access.redhat.com/articles/7004769
|
||||||
|
Patch397: 00397-tarfile-filter.patch
|
||||||
|
|
||||||
|
# 00415 #
|
||||||
|
# [CVE-2023-27043] gh-102988: Reject malformed addresses in email.parseaddr() (#111116)
|
||||||
|
#
|
||||||
|
# Detect email address parsing errors and return empty tuple to
|
||||||
|
# indicate the parsing error (old API). Add an optional 'strict'
|
||||||
|
# parameter to getaddresses() and parseaddr() functions. Patch by
|
||||||
|
# Thomas Dwyer.
|
||||||
|
#
|
||||||
|
# Upstream PR: https://github.com/python/cpython/pull/111116
|
||||||
|
#
|
||||||
|
# This patch implements the possibility to restore the old behavior via
|
||||||
|
# config file or environment variable.
|
||||||
|
Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch
|
||||||
|
|
||||||
|
# 00422 # a353cebef737c41420dc7ae2469dd657371b8881
|
||||||
|
# Fix tests for XMLPullParser with Expat 2.6.0
|
||||||
|
#
|
||||||
|
# Feeding the parser by too small chunks defers parsing to prevent
|
||||||
|
# CVE-2023-52425. Future versions of Expat may be more reactive.
|
||||||
|
Patch422: 00422-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch
|
||||||
|
|
||||||
|
# 00471 # fc5f344f7e15c13dbf41824a1b7a82d92205f79d
|
||||||
|
# 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)
|
||||||
|
Patch471: 00471-cve-2025-12084.patch
|
||||||
|
|
||||||
|
# 00473 # 7e68b796abe391a467dba42b6641053aac726d67
|
||||||
|
# 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
|
||||||
|
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 ^^^)
|
# (New patches go here ^^^)
|
||||||
#
|
#
|
||||||
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
|
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
|
||||||
@ -768,6 +852,9 @@ version once Python %{pybasever} is stable.
|
|||||||
%autopatch -M 188
|
%autopatch -M 188
|
||||||
|
|
||||||
%if %{with rpmwheels}
|
%if %{with rpmwheels}
|
||||||
|
# Temporary workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1954999
|
||||||
|
%{?!apply_patch:%define apply_patch(qp:m:) {%__apply_patch %**}}
|
||||||
|
|
||||||
%apply_patch -q %{PATCH189}
|
%apply_patch -q %{PATCH189}
|
||||||
rm Lib/ensurepip/_bundled/*.whl
|
rm Lib/ensurepip/_bundled/*.whl
|
||||||
%endif
|
%endif
|
||||||
@ -854,6 +941,7 @@ BuildPython() {
|
|||||||
ConfName=$1
|
ConfName=$1
|
||||||
ExtraConfigArgs=$2
|
ExtraConfigArgs=$2
|
||||||
MoreCFlags=$3
|
MoreCFlags=$3
|
||||||
|
MoreCFlagsNodist=$4
|
||||||
|
|
||||||
# Each build is done in its own directory
|
# Each build is done in its own directory
|
||||||
ConfDir=build/$ConfName
|
ConfDir=build/$ConfName
|
||||||
@ -888,7 +976,7 @@ BuildPython() {
|
|||||||
$ExtraConfigArgs \
|
$ExtraConfigArgs \
|
||||||
%{nil}
|
%{nil}
|
||||||
|
|
||||||
%global flags_override EXTRA_CFLAGS="$MoreCFlags" CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags"
|
%global flags_override EXTRA_CFLAGS="$MoreCFlags" CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags $MoreCFlagsNodist"
|
||||||
|
|
||||||
%if %{without bootstrap}
|
%if %{without bootstrap}
|
||||||
# Regenerate generated files (needs python3)
|
# Regenerate generated files (needs python3)
|
||||||
@ -911,12 +999,14 @@ BuildPython() {
|
|||||||
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1818857
|
# See also: https://bugzilla.redhat.com/show_bug.cgi?id=1818857
|
||||||
BuildPython debug \
|
BuildPython debug \
|
||||||
"--without-ensurepip --with-pydebug" \
|
"--without-ensurepip --with-pydebug" \
|
||||||
"-O0 -Wno-cpp"
|
"%{optflags_debug}" \
|
||||||
|
""
|
||||||
%endif # with debug_build
|
%endif # with debug_build
|
||||||
|
|
||||||
BuildPython optimized \
|
BuildPython optimized \
|
||||||
"--without-ensurepip %{optimizations_flag}" \
|
"--without-ensurepip %{optimizations_flag}" \
|
||||||
""
|
"" \
|
||||||
|
"%{optflags_optimized}"
|
||||||
|
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# Installing the built code:
|
# Installing the built code:
|
||||||
@ -1015,7 +1105,7 @@ EOF
|
|||||||
%if %{with debug_build}
|
%if %{with debug_build}
|
||||||
InstallPython debug \
|
InstallPython debug \
|
||||||
%{py_INSTSONAME_debug} \
|
%{py_INSTSONAME_debug} \
|
||||||
-O0 \
|
"%{optflags_debug}" \
|
||||||
%{LDVERSION_debug}
|
%{LDVERSION_debug}
|
||||||
%endif # with debug_build
|
%endif # with debug_build
|
||||||
|
|
||||||
@ -1442,6 +1532,10 @@ CheckPython optimized
|
|||||||
%dir %{pylibdir}/site-packages/
|
%dir %{pylibdir}/site-packages/
|
||||||
%dir %{pylibdir}/site-packages/__pycache__/
|
%dir %{pylibdir}/site-packages/__pycache__/
|
||||||
%{pylibdir}/site-packages/README.txt
|
%{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
|
%{pylibdir}/*.py
|
||||||
%dir %{pylibdir}/__pycache__/
|
%dir %{pylibdir}/__pycache__/
|
||||||
%{pylibdir}/__pycache__/*%{bytecode_suffixes}
|
%{pylibdir}/__pycache__/*%{bytecode_suffixes}
|
||||||
@ -1767,6 +1861,9 @@ CheckPython optimized
|
|||||||
%{dynload_dir}/_testinternalcapi.%{SOABI_debug}.so
|
%{dynload_dir}/_testinternalcapi.%{SOABI_debug}.so
|
||||||
%{dynload_dir}/_testmultiphase.%{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
|
%endif # with debug_build
|
||||||
|
|
||||||
# We put the debug-gdb.py file inside /usr/lib/debug to avoid noise from ldconfig
|
# We put the debug-gdb.py file inside /usr/lib/debug to avoid noise from ldconfig
|
||||||
@ -1790,6 +1887,149 @@ CheckPython optimized
|
|||||||
# ======================================================
|
# ======================================================
|
||||||
|
|
||||||
%changelog
|
%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
|
||||||
|
|
||||||
|
* Fri Jun 27 2025 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.9.23-1
|
||||||
|
- Update to 3.9.23
|
||||||
|
- Security fixes for CVE-2025-4517, CVE-2025-4330, CVE-2025-4138, CVE-2024-12718, CVE-2025-4435
|
||||||
|
Resolves: RHEL-98051, RHEL-98024, RHEL-98242, RHEL-98193, RHEL-98218
|
||||||
|
|
||||||
|
* Mon Jun 23 2025 Tobias Urdin <tobias.urdin@binero.com> - 3.9.21-3
|
||||||
|
- Add systemtap-sdt-devel build dependency
|
||||||
|
Resolves: RHEL-99500
|
||||||
|
|
||||||
|
* Mon Feb 10 2025 Charalampos Stratakis <cstratak@redhat.com> - 3.9.21-2
|
||||||
|
- Security fix for CVE-2025-0938
|
||||||
|
Resolves: RHEL-77263
|
||||||
|
|
||||||
|
* Wed Dec 04 2024 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.9.21-1
|
||||||
|
- Update to 3.9.21
|
||||||
|
- Security fix for CVE-2024-11168 and CVE-2024-9287
|
||||||
|
Resolves: RHEL-64889
|
||||||
|
Resolves: RHEL-69942
|
||||||
|
|
||||||
|
* Mon Sep 09 2024 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.9.20-1
|
||||||
|
- Update to 3.9.20
|
||||||
|
Resolves: RHEL-57422
|
||||||
|
|
||||||
|
* Fri Aug 23 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.9.19-8
|
||||||
|
- Security fix for CVE-2024-8088
|
||||||
|
Resolves: RHEL-55967
|
||||||
|
|
||||||
|
* Tue Aug 13 2024 Lumír Balhar <lbalhar@redhat.com> - 3.9.19-7
|
||||||
|
- Security fix for CVE-2024-6923
|
||||||
|
Resolves: RHEL-53045
|
||||||
|
|
||||||
|
* Thu Aug 01 2024 Miro Hrončok <mhroncok@redhat.com> - 3.9.19-6
|
||||||
|
- Ensure 3rd party extension modules for the debug build use the -O0 flag
|
||||||
|
|
||||||
|
* Thu Jul 25 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.9.19-5
|
||||||
|
- Properly propagate the optimization flags to C extensions
|
||||||
|
|
||||||
|
* Thu Jul 18 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.9.19-4
|
||||||
|
- Build Python with -O3
|
||||||
|
- https://fedoraproject.org/wiki/Changes/Python_built_with_gcc_O3
|
||||||
|
|
||||||
|
* Thu Jul 18 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.9.19-3
|
||||||
|
- Security fix for CVE-2024-4032
|
||||||
|
Resolves: RHEL-44107
|
||||||
|
|
||||||
|
* Tue Jun 11 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.9.19-2
|
||||||
|
- Enable importing of hash-based .pyc files under FIPS mode
|
||||||
|
Resolves: RHEL-40750
|
||||||
|
|
||||||
|
* Mon Apr 22 2024 Charalampos Stratakis <cstratak@redhat.com> - 3.9.19-1
|
||||||
|
- Update to 3.9.19
|
||||||
|
- Security fixes for CVE-2023-6597 and CVE-2024-0450
|
||||||
|
- Fix tests for XMLPullParser with Expat with fixed CVE
|
||||||
|
Resolves: RHEL-33679, RHEL-33691
|
||||||
|
|
||||||
|
* Wed Jan 24 2024 Lumír Balhar <lbalhar@redhat.com> - 3.9.18-3
|
||||||
|
- Fix tests on s390x with hw acceleration
|
||||||
|
Resolves: RHEL-13043
|
||||||
|
|
||||||
|
* Thu Jan 04 2024 Lumír Balhar <lbalhar@redhat.com> - 3.9.18-2
|
||||||
|
- Security fix for CVE-2023-27043
|
||||||
|
Resolves: RHEL-20613
|
||||||
|
|
||||||
|
* Thu Sep 07 2023 Charalampos Stratakis <cstratak@redhat.com> - 3.9.18-1
|
||||||
|
- Update to 3.9.18
|
||||||
|
- Security fix for CVE-2023-40217
|
||||||
|
Resolves: RHEL-3043
|
||||||
|
|
||||||
|
* Wed Aug 09 2023 Petr Viktorin <pviktori@redhat.com> - 3.9.17-2
|
||||||
|
- Fix symlink handling in the fix for CVE-2023-24329
|
||||||
|
Resolves: rhbz#263261
|
||||||
|
|
||||||
|
* Mon Jun 26 2023 Charalampos Stratakis <cstratak@redhat.com> - 3.9.17-1
|
||||||
|
- Update to 3.9.17
|
||||||
|
- Security fix for CVE-2023-24329
|
||||||
|
Resolves: rhbz#2173917
|
||||||
|
|
||||||
|
* Tue Mar 07 2023 Petr Viktorin <pviktori@redhat.com> - 3.9.16-2
|
||||||
|
- Add filters for tarfile extraction (CVE-2007-4559, PEP-706)
|
||||||
|
Resolves: rhbz#263261
|
||||||
|
|
||||||
|
* Thu Dec 08 2022 Charalampos Stratakis <cstratak@redhat.com> - 3.9.16-1
|
||||||
|
- Update to 3.9.16
|
||||||
|
- Security fixes for CVE-2022-42919 and CVE-2022-45061
|
||||||
|
Resolves: rhbz#2138705, rhbz#2144072
|
||||||
|
|
||||||
|
* Wed Sep 21 2022 Charalampos Stratakis <cstratak@redhat.com> - 3.9.14-1
|
||||||
|
- Update to 3.9.14
|
||||||
|
- Security fixes for CVE-2020-10735 and CVE-2021-28861
|
||||||
|
Resolves: rhbz#2120642, rhbz#1834423, rhbz#2128249
|
||||||
|
|
||||||
|
* Mon Jul 25 2022 Lumír Balhar <lbalhar@redhat.com> - 3.9.13-3
|
||||||
|
- Fix test_get_ciphers in test_ssl.py for FIPS mode
|
||||||
|
Resolves: rhbz#2058233
|
||||||
|
|
||||||
|
* Thu Jun 09 2022 Charalampos Stratakis <cstratak@redhat.com> - 3.9.13-2
|
||||||
|
- Security fix for CVE-2015-20107
|
||||||
|
Resolves: rhbz#2075390
|
||||||
|
|
||||||
|
* Wed Jun 01 2022 Charalampos Stratakis <cstratak@redhat.com> - 3.9.13-1
|
||||||
|
- Update to 3.9.13
|
||||||
|
Resolves: rhbz#2054702, rhbz#2059951
|
||||||
|
|
||||||
|
* Wed Feb 09 2022 Charalampos Stratakis <cstratak@redhat.com> - 3.9.10-2
|
||||||
|
- Fix undefined behavior in Modules/_hashopenssl.c
|
||||||
|
Resolves: rhbz#1942527
|
||||||
|
|
||||||
|
* Mon Jan 17 2022 Charalampos Stratakis <cstratak@redhat.com> - 3.9.10-1
|
||||||
|
- Update to 3.9.10
|
||||||
|
- Support OpenSSL FIPS mode
|
||||||
|
Resolves: rhbz#1942527, rhbz#1835169
|
||||||
|
|
||||||
|
* Sat Jan 08 2022 Miro Hrončok <mhroncok@redhat.com> - 3.9.9-4
|
||||||
|
- Instruct pip to use distutils
|
||||||
|
- Instruct pypa/distutils to add /local/ addition to prefix
|
||||||
|
|
||||||
* Mon Nov 22 2021 Tomas Orsava <torsava@redhat.com> - 3.9.9-2
|
* Mon Nov 22 2021 Tomas Orsava <torsava@redhat.com> - 3.9.9-2
|
||||||
- Read pre-packaged Python wheels from a newly versioned directory
|
- Read pre-packaged Python wheels from a newly versioned directory
|
||||||
/usr/share/python3-wheels
|
/usr/share/python3-wheels
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user