Compare commits

...
Sign in to create a new pull request.

6 commits

Author SHA1 Message Date
Miro Hrončok
0ca3f59c07 On EL 9, also supports reparse deferral in expat
This replaces one downstream-only patch with another.
Yet arguably, this is the safer thing to do.

Read the patch description for details; won't copy paste them here.

Also, require expat >= version-release when expat < 2.7.4.

Assisted-By: Claude Opus 4.6
2026-08-13 12:47:37 +02:00
Karolina Surma
b93f3ee7d7 Update to Python 3.13.15 2026-08-11 10:32:30 +02:00
Fedora Release Engineering
8cc71e2467 Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild 2026-07-16 22:48:21 +00:00
Lumir Balhar
ae2158c990 Run a new test to monitor changes in required symbols 2026-07-01 12:34:13 +02:00
Karolina Surma
a5e28d44e7 Update to Python 3.13.14 2026-06-11 16:12:16 +02:00
Miro Hrončok
58718512ed Explicitly build with OpenSSL 3 for now
https://fedoraproject.org/wiki/Changes/OpenSSL40
2026-04-09 13:26:27 +02:00
8 changed files with 198 additions and 287 deletions

View file

@ -1,102 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Charalampos Stratakis <cstratak@redhat.com>
Date: Tue, 3 Jun 2025 03:02:15 +0200
Subject: 00464: Enable PAC and BTI protections for aarch64
Apply protection against ROP/JOP attacks for aarch64 on asm_trampoline.S
The BTI flag must be applied in the assembler sources for this class
of attacks to be mitigated on newer aarch64 processors.
Upstream PR: https://github.com/python/cpython/pull/130864/files
The upstream patch is incomplete but only for the case where
frame pointers are not used on 3.13+.
Since on Fedora we always compile with frame pointers the BTI/PAC
hardware protections can be enabled without losing Perf unwinding.
---
Python/asm_trampoline.S | 4 +++
Python/asm_trampoline_aarch64.h | 50 +++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 Python/asm_trampoline_aarch64.h
diff --git a/Python/asm_trampoline.S b/Python/asm_trampoline.S
index a14e68c0e8..2513cde4e7 100644
--- a/Python/asm_trampoline.S
+++ b/Python/asm_trampoline.S
@@ -1,3 +1,5 @@
+#include "asm_trampoline_aarch64.h"
+
.text
.globl _Py_trampoline_func_start
# The following assembly is equivalent to:
@@ -21,10 +23,12 @@ _Py_trampoline_func_start:
#if defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__)
// ARM64 little endian, 64bit ABI
// generate with aarch64-linux-gnu-gcc 12.1
+ SIGN_LR
stp x29, x30, [sp, -16]!
mov x29, sp
blr x3
ldp x29, x30, [sp], 16
+ VERIFY_LR
ret
#endif
#ifdef __riscv
diff --git a/Python/asm_trampoline_aarch64.h b/Python/asm_trampoline_aarch64.h
new file mode 100644
index 0000000000..4b0ec4a7dc
--- /dev/null
+++ b/Python/asm_trampoline_aarch64.h
@@ -0,0 +1,50 @@
+#ifndef ASM_TRAMPOLINE_AARCH_64_H_
+#define ASM_TRAMPOLINE_AARCH_64_H_
+
+/*
+ * References:
+ * - https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros
+ * - https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst
+ */
+
+#if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT == 1
+ #define BTI_J hint 36 /* bti j: for jumps, IE br instructions */
+ #define BTI_C hint 34 /* bti c: for calls, IE bl instructions */
+ #define GNU_PROPERTY_AARCH64_BTI 1 /* bit 0 GNU Notes is for BTI support */
+#else
+ #define BTI_J
+ #define BTI_C
+ #define GNU_PROPERTY_AARCH64_BTI 0
+#endif
+
+#if defined(__ARM_FEATURE_PAC_DEFAULT)
+ #if __ARM_FEATURE_PAC_DEFAULT & 1
+ #define SIGN_LR hint 25 /* paciasp: sign with the A key */
+ #define VERIFY_LR hint 29 /* autiasp: verify with the A key */
+ #elif __ARM_FEATURE_PAC_DEFAULT & 2
+ #define SIGN_LR hint 27 /* pacibsp: sign with the b key */
+ #define VERIFY_LR hint 31 /* autibsp: verify with the b key */
+ #endif
+ #define GNU_PROPERTY_AARCH64_POINTER_AUTH 2 /* bit 1 GNU Notes is for PAC support */
+#else
+ #define SIGN_LR BTI_C
+ #define VERIFY_LR
+ #define GNU_PROPERTY_AARCH64_POINTER_AUTH 0
+#endif
+
+/* Add the BTI and PAC support to GNU Notes section */
+#if GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_POINTER_AUTH != 0
+ .pushsection .note.gnu.property, "a"; /* Start a new allocatable section */
+ .balign 8; /* align it on a byte boundry */
+ .long 4; /* size of "GNU\0" */
+ .long 0x10; /* size of descriptor */
+ .long 0x5; /* NT_GNU_PROPERTY_TYPE_0 */
+ .asciz "GNU";
+ .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
+ .long 4; /* Four bytes of data */
+ .long (GNU_PROPERTY_AARCH64_BTI|GNU_PROPERTY_AARCH64_POINTER_AUTH); /* BTI or PAC is enabled */
+ .long 0; /* padding for 8 byte alignment */
+ .popsection; /* end the section */
+#endif
+
+#endif

View file

@ -0,0 +1,133 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Wed, 12 Aug 2026 15:18:39 +0200
Subject: 00466: Downstream only: Lower XML_COMBINED_VERSION threshold for
reparse deferral
RHEL 9 expat 2.5.0 has XML_SetReparseDeferralEnabled backported
via the CVE-2023-52425 fix, but XML_COMBINED_VERSION remains 20500.
CPython's #if XML_COMBINED_VERSION >= 20600 guards compile the setter
as a no-op, so SetReparseDeferralEnabled silently does nothing and
GetReparseDeferralEnabled always returns False, even though the expat
library actually supports (and enables) reparse deferral.
Lower the threshold from 20600 to 20500 so that CPython uses the
backported function. This makes the Python API actually work on RHEL 9
and fixes test failures (test_reparse_deferral_disabled,
test_flush_reparse_deferral_disabled, test_simple_xml_chunk_*).
The spec file BuildRequires expat-devel >= 2.5.0-2 to ensure the
backported function is available.
---
Lib/test/test_pyexpat.py | 6 +++---
Lib/test/test_sax.py | 4 ++--
Lib/test/test_xml_etree.py | 4 ++--
Modules/pyexpat.c | 6 +++---
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py
index ae7cec6540..7f73a8c5e7 100644
--- a/Lib/test/test_pyexpat.py
+++ b/Lib/test/test_pyexpat.py
@@ -1001,7 +1001,7 @@ def test_error_path_no_crash(self):
class ReparseDeferralTest(unittest.TestCase):
def test_getter_setter_round_trip(self):
parser = expat.ParserCreate()
- enabled = (expat.version_info >= (2, 6, 0))
+ enabled = (expat.version_info >= (2, 5, 0))
self.assertIs(parser.GetReparseDeferralEnabled(), enabled)
parser.SetReparseDeferralEnabled(False)
@@ -1010,7 +1010,7 @@ def test_getter_setter_round_trip(self):
self.assertIs(parser.GetReparseDeferralEnabled(), enabled)
def test_reparse_deferral_enabled(self):
- if expat.version_info < (2, 6, 0):
+ if expat.version_info < (2, 5, 0):
self.skipTest(f'Expat {expat.version_info} does not '
'support reparse deferral')
@@ -1041,7 +1041,7 @@ def start_element(name, _):
parser = expat.ParserCreate()
parser.StartElementHandler = start_element
- if expat.version_info >= (2, 6, 0):
+ if expat.version_info >= (2, 5, 0):
parser.SetReparseDeferralEnabled(False)
self.assertFalse(parser.GetReparseDeferralEnabled())
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 9b3014a94a..0e38c9488e 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -1215,7 +1215,7 @@ def test_expat_incremental_reset(self):
self.assertEqual(result.getvalue(), start + b"<doc>text</doc>")
- @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
+ @unittest.skipIf(pyexpat.version_info < (2, 5, 0),
f'Expat {pyexpat.version_info} does not '
'support reparse deferral')
def test_flush_reparse_deferral_enabled(self):
@@ -1249,7 +1249,7 @@ def test_flush_reparse_deferral_disabled(self):
for chunk in ("<doc", ">"):
parser.feed(chunk)
- if pyexpat.version_info >= (2, 6, 0):
+ if pyexpat.version_info >= (2, 5, 0):
parser._parser.SetReparseDeferralEnabled(False)
self.assertEqual(result.getvalue(), start) # i.e. no elements started
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 4a76a5be1e..effb899d7b 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1804,7 +1804,7 @@ def test_unknown_event(self):
with self.assertRaisesRegex(ValueError, "unknown event 'bogus'"):
ET.XMLPullParser(events=(x.decode() for x in (b'start', b'end', b'bogus')))
- @unittest.skipIf(pyexpat.version_info < (2, 6, 0),
+ @unittest.skipIf(pyexpat.version_info < (2, 5, 0),
f'Expat {pyexpat.version_info} does not '
'support reparse deferral')
def test_flush_reparse_deferral_enabled(self):
@@ -1834,7 +1834,7 @@ def test_flush_reparse_deferral_disabled(self):
for chunk in ("<doc", ">"):
parser.feed(chunk)
- if pyexpat.version_info >= (2, 6, 0):
+ if pyexpat.version_info >= (2, 5, 0):
if not ET is pyET:
self.skipTest(f'XMLParser.(Get|Set)ReparseDeferralEnabled '
'methods not available in C')
diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c
index 9e5d84eb5e..b008fe66c1 100644
--- a/Modules/pyexpat.c
+++ b/Modules/pyexpat.c
@@ -781,7 +781,7 @@ pyexpat_xmlparser_SetReparseDeferralEnabled_impl(xmlparseobject *self,
int enabled)
/*[clinic end generated code: output=5ec539e3b63c8c49 input=021eb9e0bafc32c5]*/
{
-#if XML_COMBINED_VERSION >= 20600
+#if XML_COMBINED_VERSION >= 20500
XML_SetReparseDeferralEnabled(self->itself, enabled ? XML_TRUE : XML_FALSE);
self->reparse_deferral_enabled = (bool)enabled;
#endif
@@ -1446,7 +1446,7 @@ newxmlparseobject(pyexpat_state *state, const char *encoding,
self->ns_prefixes = 0;
self->handlers = NULL;
self->intern = Py_XNewRef(intern);
-#if XML_COMBINED_VERSION >= 20600
+#if XML_COMBINED_VERSION >= 20500
self->reparse_deferral_enabled = true;
#else
self->reparse_deferral_enabled = false;
@@ -2332,7 +2332,7 @@ pyexpat_exec(PyObject *mod)
#else
capi->SetHashSalt16Bytes = NULL;
#endif
-#if XML_COMBINED_VERSION >= 20600
+#if XML_COMBINED_VERSION >= 20500
capi->SetReparseDeferralEnabled = XML_SetReparseDeferralEnabled;
#else
capi->SetReparseDeferralEnabled = NULL;

View file

@ -1,69 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Karolina Surma <ksurma@redhat.com>
Date: Tue, 24 Jun 2025 11:12:13 +0200
Subject: 00466: Downstream only: Skip tests not working with older expat
version
We want to run these tests in Fedora and EPEL 10, but not in EPEL 9,
which has too old version of expat. We set the upper bound version
in the conditionalized skip to a release available in CentOS Stream 10,
which is tested as working.
---
Lib/test/test_pyexpat.py | 2 ++
Lib/test/test_sax.py | 2 ++
Lib/test/test_xml_etree.py | 6 ++++++
3 files changed, 10 insertions(+)
diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py
index 2309353503..fca62245d4 100644
--- a/Lib/test/test_pyexpat.py
+++ b/Lib/test/test_pyexpat.py
@@ -901,6 +901,8 @@ def start_element(name, _):
self.assertEqual(started, ['doc'])
+ @unittest.skipIf(expat.version_info < (2, 7, 1),
+ f"Skip for expat < 2.7.1 (version available in RHEL 10)")
def test_reparse_deferral_disabled(self):
started = []
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 9b3014a94a..90401e0d8f 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -1240,6 +1240,8 @@ def test_flush_reparse_deferral_enabled(self):
self.assertEqual(result.getvalue(), start + b"<doc></doc>")
+ @unittest.skipIf(pyexpat.version_info < (2, 7, 1),
+ f"Skip for expat < 2.7.1 (version available in RHEL 10)")
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 597ec83061..bf2db1779c 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1574,9 +1574,13 @@ def test_simple_xml(self, chunk_size=None, flush=False):
self.assert_event_tags(parser, [('end', 'root')])
self.assertIsNone(parser.close())
+ @unittest.skipIf(pyexpat.version_info < (2, 7, 1),
+ f"Skip for expat < 2.7.1 (version available in RHEL 10)")
def test_simple_xml_chunk_1(self):
self.test_simple_xml(chunk_size=1, flush=True)
+ @unittest.skipIf(pyexpat.version_info < (2, 7, 1),
+ f"Skip for expat < 2.7.1 (version available in RHEL 10)")
def test_simple_xml_chunk_5(self):
self.test_simple_xml(chunk_size=5, flush=True)
@@ -1803,6 +1807,8 @@ def test_flush_reparse_deferral_enabled(self):
self.assert_event_tags(parser, [('end', 'doc')])
+ @unittest.skipIf(pyexpat.version_info < (2, 7, 1),
+ f"Skip for expat < 2.7.1 (version available in RHEL 10)")
def test_flush_reparse_deferral_disabled(self):
parser = ET.XMLPullParser(events=('start', 'end'))

View file

@ -1,59 +0,0 @@
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
Reject control characters in IMAP commands
---
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 141e639894..f282e5c061 100644
--- a/Lib/imaplib.py
+++ b/Lib/imaplib.py
@@ -132,7 +132,7 @@
# 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:
@@ -1000,6 +1000,8 @@ def _command(self, name, *args):
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 9f1f682d02..820c2a5db5 100644
--- a/Lib/test/test_imaplib.py
+++ b/Lib/test/test_imaplib.py
@@ -515,6 +515,12 @@ def test_login(self):
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.

View file

@ -81,10 +81,10 @@ index 2a17c891dd..64017c666c 100644
}
#endif
diff --git a/Makefile.pre.in b/Makefile.pre.in
index ecf77bdc41..91bfd06a78 100644
index 2363b99a25..f1a07645f0 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -3153,3 +3153,6 @@ MODULE__MULTIBYTECODEC_DEPS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h
@@ -3159,3 +3159,6 @@ MODULE__MULTIBYTECODEC_DEPS=$(srcdir)/Modules/cjkcodecs/multibytecodec.h
# Local Variables:
# mode: makefile
# End:
@ -92,10 +92,10 @@ index ecf77bdc41..91bfd06a78 100644
+# Fedora-specific, downstream only
+PY_STDMODULE_CFLAGS += -D_PyHack_check_version_on_modinit=1
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 0200f59020..bb647555c0 100644
index 1996488a0e..cfdffd8ec4 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -4763,6 +4763,12 @@ curses_destructor(PyObject *op)
@@ -5011,6 +5011,12 @@ curses_destructor(PyObject *op)
PyMODINIT_FUNC
PyInit__curses(void)
{
@ -109,10 +109,10 @@ index 0200f59020..bb647555c0 100644
/* Initialize object type */
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 14efe18db5..70597c2815 100644
index 4e8d75e8e1..32e58755aa 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -3431,6 +3431,12 @@ static struct PyModuleDef _tkintermodule = {
@@ -3499,6 +3499,12 @@ static struct PyModuleDef _tkintermodule = {
PyMODINIT_FUNC
PyInit__tkinter(void)
{
@ -143,10 +143,10 @@ index 0b85187e5f..87f358ed07 100644
m = PyModule_Create(&module_def);
if (m == NULL)
diff --git a/Modules/readline.c b/Modules/readline.c
index f9362c312d..66f1ec65a6 100644
index 7a612deae4..8b2f47eec1 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -1540,6 +1540,12 @@ static struct PyModuleDef readlinemodule = {
@@ -1548,6 +1548,12 @@ static struct PyModuleDef readlinemodule = {
PyMODINIT_FUNC
PyInit_readline(void)
{

View file

@ -43,6 +43,9 @@ discover:
- name: marshalparser
path: /marshalparser
test: "VERSION=${pybasever} SAMPLE=10 ./test_marshalparser_compatibility.sh"
- name: required_symbols
path: /required-symbols
test: "VERSION=${pybasever} ./check.sh"
prepare:
- name: Install dependencies
@ -62,8 +65,9 @@ prepare:
- virtualenv # for virtualenv tests
- glibc-all-langpacks # for locale tests
- marshalparser # for testing compatibility (magic numbers) with marshalparser
- binutils # for nm (symbol inspection)
- rpm # for debugging
- dnf # for upgrade
- dnf # for upgrade and downgrade
- name: Update packages
how: shell
script: dnf upgrade -y

View file

@ -45,11 +45,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}.13
%global general_version %{pybasever}.15
#global prerel ...
%global upstream_version %{general_version}%{?prerel}
Version: %{general_version}%{?prerel:~%{prerel}}
Release: 1%{?dist}
Release: 2%{?dist}
License: Python-2.0.1
@ -109,31 +109,30 @@ License: Python-2.0.1
# This needs to be manually updated when we update Python.
# Explore the sources tarball (you need the version before %%prep is executed):
# $ tar -tf Python-%%{upstream_version}.tar.xz | grep whl
%global pip_version 26.0.1
%global pip_version 26.2.1
%global setuptools_version 79.0.1
# All of those also include a list of indirect bundled libs:
# pip
# $ %%{_rpmconfigdir}/pythonbundles.py <(unzip -p Lib/ensurepip/_bundled/pip-*.whl pip/_vendor/vendor.txt)
%global pip_bundled_provides %{expand:
Provides: bundled(python3dist(cachecontrol)) = 0.14.4
Provides: bundled(python3dist(certifi)) = 2026.1.4
Provides: bundled(python3dist(dependency-groups)) = 1.3.1
Provides: bundled(python3dist(distlib)) = 0.4
Provides: bundled(python3dist(certifi)) = 2026.6.17
Provides: bundled(python3dist(distlib)) = 0.4.2
Provides: bundled(python3dist(distro)) = 1.9
Provides: bundled(python3dist(idna)) = 3.11
Provides: bundled(python3dist(idna)) = 3.18
Provides: bundled(python3dist(msgpack)) = 1.1.2
Provides: bundled(python3dist(packaging)) = 26
Provides: bundled(python3dist(platformdirs)) = 4.5.1
Provides: bundled(python3dist(pygments)) = 2.19.2
Provides: bundled(python3dist(packaging)) = 26.2
Provides: bundled(python3dist(platformdirs)) = 4.10
Provides: bundled(python3dist(pygments)) = 2.20
Provides: bundled(python3dist(pyproject-hooks)) = 1.2
Provides: bundled(python3dist(requests)) = 2.32.5
Provides: bundled(python3dist(requests)) = 2.34.2
Provides: bundled(python3dist(resolvelib)) = 1.2.1
Provides: bundled(python3dist(rich)) = 14.2
Provides: bundled(python3dist(setuptools)) = 70.3
Provides: bundled(python3dist(tomli)) = 2.3
Provides: bundled(python3dist(tomli)) = 2.4.1
Provides: bundled(python3dist(tomli-w)) = 1.2
Provides: bundled(python3dist(truststore)) = 0.10.4
Provides: bundled(python3dist(urllib3)) = 1.26.20
Provides: bundled(python3dist(urllib3)) = 2.7
}
# setuptools
# vendor.txt not in .whl
@ -255,7 +254,7 @@ Obsoletes: python%{pybasever}%{?1:-%{1}}\
BuildRequires: autoconf
BuildRequires: bluez-libs-devel
BuildRequires: bzip2-devel
BuildRequires: expat-devel
BuildRequires: expat-devel >= 2.5.0-2
BuildRequires: findutils
BuildRequires: gcc
BuildRequires: gdbm-devel
@ -268,7 +267,6 @@ BuildRequires: libuuid-devel
BuildRequires: make
BuildRequires: mpdecimal-devel
BuildRequires: ncurses-devel
BuildRequires: openssl-devel
BuildRequires: pkgconfig
BuildRequires: python-rpm-macros
BuildRequires: readline-devel
@ -281,6 +279,10 @@ BuildRequires: xz-devel
BuildRequires: zlib-devel
BuildRequires: /usr/bin/dtrace
# Support for OpenSSL 4 only landed in Python 3.15 for now
# https://github.com/python/cpython/issues/146207
BuildRequires: (openssl-devel < 1:4 or openssl3-devel)
%if %{undefined rhel}
BuildRequires: libb2-devel
%endif
@ -368,37 +370,24 @@ Source11: idle3.appdata.xml
# pypa/distutils integration: https://github.com/pypa/distutils/pull/70
Patch251: 00251-change-user-install-location.patch
# 00464 # 292acffec7a379cb6d1f3c47b9e5a2f170bbadb6
# Enable PAC and BTI protections for aarch64
# 00466 # 713a1368544eddd55088d67f88a23ce31722a4cb
# Downstream only: Lower XML_COMBINED_VERSION threshold for reparse deferral
#
# Apply protection against ROP/JOP attacks for aarch64 on asm_trampoline.S
# RHEL 9 expat 2.5.0 has XML_SetReparseDeferralEnabled backported
# via the CVE-2023-52425 fix, but XML_COMBINED_VERSION remains 20500.
# CPython's #if XML_COMBINED_VERSION >= 20600 guards compile the setter
# as a no-op, so SetReparseDeferralEnabled silently does nothing and
# GetReparseDeferralEnabled always returns False, even though the expat
# library actually supports (and enables) reparse deferral.
#
# The BTI flag must be applied in the assembler sources for this class
# of attacks to be mitigated on newer aarch64 processors.
# Lower the threshold from 20600 to 20500 so that CPython uses the
# backported function. This makes the Python API actually work on RHEL 9
# and fixes test failures (test_reparse_deferral_disabled,
# test_flush_reparse_deferral_disabled, test_simple_xml_chunk_*).
#
# Upstream PR: https://github.com/python/cpython/pull/130864/files
#
# The upstream patch is incomplete but only for the case where
# frame pointers are not used on 3.13+.
#
# Since on Fedora we always compile with frame pointers the BTI/PAC
# hardware protections can be enabled without losing Perf unwinding.
Patch464: 00464-enable-pac-and-bti-protections-for-aarch64.patch
# 00466 # e10760fb955ee33d2917f8a57bb4e24d71e5341c
# Downstream only: Skip tests not working with older expat version
#
# We want to run these tests in Fedora and EPEL 10, but not in EPEL 9,
# which has too old version of expat. We set the upper bound version
# in the conditionalized skip to a release available in CentOS Stream 10,
# which is tested as working.
Patch466: 00466-downstream-only-skip-tests-not-working-with-older-expat-version.patch
# 00474 # 837ddca0372fa87ff9cee47142200caa21e77def
# CVE-2025-15366
#
# Reject control characters in IMAP commands
Patch474: 00474-cve-2025-15366.patch
# The spec file BuildRequires expat-devel >= 2.5.0-2 to ensure the
# backported function is available.
Patch466: 00466-downstream-only-lower-xml_combined_version-threshold-for-reparse-deferral.patch
# 00475 # d44fac01037662db286449a78c8fb819788f764c
# CVE-2025-15367
@ -545,7 +534,7 @@ Summary: Python runtime libraries
# Combined manually from https://docs.python.org/3.13/license.html
# Hash of Doc/license.rst which is compared in %%prep, generated with:
# $ sha256sum Doc/license.rst | cut -f1 -d" "
%global license_file_hash 62f2c9c2c75d511170eb464ad5f83b78cc1f37eb2eb49c2846c9aa6c4557ee99
%global license_file_hash 952ac05720d7f1dcb63589b35eb0931b1442eb250230a4ad31198eddf0ad6abc
# Licenses of incorporated software:
# Mersenne Twister in _random C extension contains code under BSD-3-Clause
# socket.getaddrinfo() and socket.getnameinfo() are BSD-3-Clause
@ -568,10 +557,11 @@ Summary: Python runtime libraries
# mimalloc is MIT
# parts of asyncio from uvloop are MIT
# Python/qsbr.c is adapted from code under BSD-2-Clause
# An extract of the `Unicode Character Database` converted to an internal format is Unicode-3.0
# Bundled libb2 is not declared in the upstream document, but it's:
# CC0-1.0, covered by grandfathering exception
# We don't query upstream for changes, as 3.13 is the last Python version containing it.
%global libs_license Python-2.0.1 AND CC0-1.0 AND MIT AND BSD-3-Clause AND MIT-CMU AND HPND-SMC AND BSD-2-Clause AND dtoa
%global libs_license Python-2.0.1 AND CC0-1.0 AND MIT AND BSD-3-Clause AND MIT-CMU AND HPND-SMC AND BSD-2-Clause AND dtoa AND Unicode-3.0
%if %{with rpmwheels}
Requires: %{python_wheel_pkg_prefix}-pip-wheel >= 23.1.2
License: %{libs_license}
@ -618,10 +608,12 @@ Requires: tzdata
# This breaks many things, including python -m venv.
# We avoid this problem by requiring at least the same version of expat that
# was used during the build time.
# We also include release, in case pyxpat uses ABI that was backported
# (e.g. XML_SetReparseDeferralEnabled was added in c9s expat 2.5.0-2).
# Other subpackages (like -debug) also need this, but they all depend on -libs.
# Since expat 2.7.4, the library has versioned symbols and this is no longer needed,
# as the generated requirement will be in the form of libexpat.so.1(LIBEXPAT_2.7.2) etc.
%global expat_version %(LANG=C rpm -q --qf '%%{version}' expat.%{_target_cpu} | sed 's/.*not installed/0/')
%global expat_version %(LANG=C rpm -q --qf '%%{version}-%%{release}' expat.%{_target_cpu} | sed 's/.*not installed/0/')
%if v"%{expat_version}" < v"2.7.4"
Requires: expat%{?_isa} >= %{expat_version}
%endif
@ -1826,6 +1818,18 @@ CheckPython freethreading
# ======================================================
%changelog
* Wed Aug 12 2026 Miro Hrončok <mhroncok@redhat.com> - 3.13.15-2
- On EPEL 9, also supports reparse deferral in expat
* Mon Aug 10 2026 Karolina Surma <ksurma@redhat.com> - 3.13.15-1
- Update to Python 3.13.15
* Thu Jul 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.14-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
* Thu Jun 11 2026 Karolina Surma <ksurma@redhat.com> - 3.13.14-1
- Update to Python 3.13.14
* Wed Apr 08 2026 Tomáš Hrnčiar <thrnciar@redhat.com> - 3.13.13-1
- Update to 3.13.13

View file

@ -1,2 +1,2 @@
SHA512 (Python-3.13.13.tar.xz) = 0ef615150a52865fe7ca0d0e106cf98488f113a56e5ae1b1437673f03880423839d04abe1999006f9835c77d8802d5ae94a1bdf63d18074a9a19c81e6f7b69e8
SHA512 (Python-3.13.13.tar.xz.asc) = 21e5235cd9a9df3546370feb55ac32539e08601b79ee7b1e39006028f192be6be0434f2f8384fdcc993b70bde7471be3b36ce9850abf0473d1fe2c7cdc98304b
SHA512 (Python-3.13.15.tar.xz) = b0ab766a3de0b4cfdbf0b93300d7330c734d3f7057577bb03e95e39da4cdade81993e769c7fa6dfdcc13b9d43a3b399d9cd89b5477b413662e9e691c1b7886b8
SHA512 (Python-3.13.15.tar.xz.asc) = 662c00be95f62e80db43cf42099fef91f764ff7a4433cadf7eb19dedb5e4775adb12878d5ed2295fcea187731de186163ad9672ab72cde62a2335ca58ec1ad86