diff --git a/tests/.fmf/version b/.fmf/version similarity index 100% rename from tests/.fmf/version rename to .fmf/version diff --git a/00001-rpath.patch b/00001-rpath.patch index 778c077..cd063e5 100644 --- a/00001-rpath.patch +++ b/00001-rpath.patch @@ -1,9 +1,10 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 13 Jan 2010 21:25:18 +0000 -Subject: [PATCH] 00001: Fixup distutils/unixccompiler.py to remove standard - library path from rpath Was Patch0 in ivazquez' python3000 specfile +Subject: 00001: Fixup distutils/unixccompiler.py to remove standard library + path from rpath +Was Patch0 in ivazquez' python3000 specfile --- Lib/distutils/unixccompiler.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/00111-no-static-lib.patch b/00111-no-static-lib.patch index 37966be..bdabed8 100644 --- a/00111-no-static-lib.patch +++ b/00111-no-static-lib.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 18 Jan 2010 17:59:07 +0000 -Subject: [PATCH] 00111: Don't try to build a libpythonMAJOR.MINOR.a +Subject: 00111: Don't try to build a libpythonMAJOR.MINOR.a MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/00189-use-rpm-wheels.patch b/00189-use-rpm-wheels.patch index dfb47f4..322da15 100644 --- a/00189-use-rpm-wheels.patch +++ b/00189-use-rpm-wheels.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 15 Aug 2018 15:36:29 +0200 -Subject: [PATCH] 00189: Instead of bundled wheels, use our RPM packaged wheels +Subject: 00189: Instead of bundled wheels, use our RPM packaged wheels We keep them in /usr/share/python-wheels @@ -12,7 +12,7 @@ We might eventually pursuit upstream support, but it's low prio 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py -index 07065c3cb7..77d7ec5a65 100644 +index d61bb089e3..77d7ec5a65 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -1,3 +1,5 @@ @@ -30,7 +30,7 @@ index 07065c3cb7..77d7ec5a65 100644 __all__ = ["version", "bootstrap"] --_SETUPTOOLS_VERSION = "58.1.0" +-_SETUPTOOLS_VERSION = "79.0.1" -_PIP_VERSION = "23.0.1" + +_WHEEL_DIR = "/usr/share/python-wheels/" diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index f961419..ecceb6c 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Michal Cyprian Date: Mon, 26 Jun 2017 16:32:56 +0200 -Subject: [PATCH] 00251: Change user install location +Subject: 00251: Change user install location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit diff --git a/00353-architecture-names-upstream-downstream.patch b/00353-architecture-names-upstream-downstream.patch index b0b955c..343ff96 100644 --- a/00353-architecture-names-upstream-downstream.patch +++ b/00353-architecture-names-upstream-downstream.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 4 Aug 2020 12:04:03 +0200 -Subject: [PATCH] 00353: Original names for architectures with different names +Subject: 00353: Original names for architectures with different names downstream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 diff --git a/00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch b/00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch index c089771..747e55d 100644 --- a/00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +++ b/00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch @@ -1,8 +1,8 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Fri, 19 Nov 2021 13:37:16 +0100 -Subject: [PATCH] 00371: Revert "bpo-1596321: Fix threading._shutdown() for the - main thread (GH-28549) (GH-28589)" +Subject: 00371: Revert "bpo-1596321: Fix threading._shutdown() for the main + thread (GH-28549) (GH-28589)" This reverts commit 94d19f606fa18a1c4d2faca1caf2f470a8ce6d46. It introduced regression causing FreeIPA's tests to fail. diff --git a/00407-gh-99086-fix-implicit-int-compiler-warning-in-configure-check-for-pthread_scope_system.patch b/00407-gh-99086-fix-implicit-int-compiler-warning-in-configure-check-for-pthread_scope_system.patch index 0c63a32..4df365e 100644 --- a/00407-gh-99086-fix-implicit-int-compiler-warning-in-configure-check-for-pthread_scope_system.patch +++ b/00407-gh-99086-fix-implicit-int-compiler-warning-in-configure-check-for-pthread_scope_system.patch @@ -1,8 +1,8 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "Erlend E. Aasland" Date: Sun, 6 Nov 2022 22:39:34 +0100 -Subject: [PATCH] 00407: gh-99086: Fix implicit int compiler warning in - configure check for PTHREAD_SCOPE_SYSTEM +Subject: 00407: gh-99086: Fix implicit int compiler warning in configure check + for PTHREAD_SCOPE_SYSTEM Co-authored-by: Sam James --- diff --git a/00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch b/00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch deleted file mode 100644 index af44881..0000000 --- a/00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch +++ /dev/null @@ -1,500 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Stinner -Date: Fri, 15 Dec 2023 16:10:40 +0100 -Subject: [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. - -Co-Authored-By: Thomas Dwyer ---- - Doc/library/email.utils.rst | 19 +- - Lib/email/utils.py | 151 ++++++++++++- - Lib/test/test_email/test_email.py | 204 +++++++++++++++++- - ...-10-20-15-28-08.gh-issue-102988.dStNO7.rst | 8 + - 4 files changed, 361 insertions(+), 21 deletions(-) - create mode 100644 Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst - -diff --git a/Doc/library/email.utils.rst b/Doc/library/email.utils.rst -index 4d0e920eb0..104229e9e5 100644 ---- a/Doc/library/email.utils.rst -+++ b/Doc/library/email.utils.rst -@@ -60,13 +60,18 @@ of the new API. - begins with angle brackets, they are stripped off. - - --.. function:: parseaddr(address) -+.. function:: parseaddr(address, *, strict=True) - - Parse address -- which should be the value of some address-containing field such - as :mailheader:`To` or :mailheader:`Cc` -- into its constituent *realname* and - *email address* parts. Returns a tuple of that information, unless the parse - fails, in which case a 2-tuple of ``('', '')`` is returned. - -+ If *strict* is true, use a strict parser which rejects malformed inputs. -+ -+ .. versionchanged:: 3.13 -+ Add *strict* optional parameter and reject malformed inputs by default. -+ - - .. function:: formataddr(pair, charset='utf-8') - -@@ -84,12 +89,15 @@ of the new API. - Added the *charset* option. - - --.. function:: getaddresses(fieldvalues) -+.. function:: getaddresses(fieldvalues, *, strict=True) - - This method returns a list of 2-tuples of the form returned by ``parseaddr()``. - *fieldvalues* is a sequence of header field values as might be returned by -- :meth:`Message.get_all `. Here's a simple -- example that gets all the recipients of a message:: -+ :meth:`Message.get_all `. -+ -+ If *strict* is true, use a strict parser which rejects malformed inputs. -+ -+ Here's a simple example that gets all the recipients of a message:: - - from email.utils import getaddresses - -@@ -99,6 +107,9 @@ of the new API. - resent_ccs = msg.get_all('resent-cc', []) - all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs) - -+ .. versionchanged:: 3.13 -+ Add *strict* optional parameter and reject malformed inputs by default. -+ - - .. function:: parsedate(date) - -diff --git a/Lib/email/utils.py b/Lib/email/utils.py -index 48d30160aa..7ca7a7c886 100644 ---- a/Lib/email/utils.py -+++ b/Lib/email/utils.py -@@ -48,6 +48,7 @@ TICK = "'" - specialsre = re.compile(r'[][\\()<>@,:;".]') - escapesre = re.compile(r'[\\"]') - -+ - def _has_surrogates(s): - """Return True if s contains surrogate-escaped binary data.""" - # This check is based on the fact that unless there are surrogates, utf8 -@@ -106,12 +107,127 @@ def formataddr(pair, charset='utf-8'): - return address - - -+def _iter_escaped_chars(addr): -+ pos = 0 -+ escape = False -+ for pos, ch in enumerate(addr): -+ if escape: -+ yield (pos, '\\' + ch) -+ escape = False -+ elif ch == '\\': -+ escape = True -+ else: -+ yield (pos, ch) -+ if escape: -+ yield (pos, '\\') - --def getaddresses(fieldvalues): -- """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" -- all = COMMASPACE.join(str(v) for v in fieldvalues) -- a = _AddressList(all) -- return a.addresslist -+ -+def _strip_quoted_realnames(addr): -+ """Strip real names between quotes.""" -+ if '"' not in addr: -+ # Fast path -+ return addr -+ -+ start = 0 -+ open_pos = None -+ result = [] -+ for pos, ch in _iter_escaped_chars(addr): -+ if ch == '"': -+ if open_pos is None: -+ open_pos = pos -+ else: -+ if start != open_pos: -+ result.append(addr[start:open_pos]) -+ start = pos + 1 -+ open_pos = None -+ -+ if start < len(addr): -+ result.append(addr[start:]) -+ -+ return ''.join(result) -+ -+ -+supports_strict_parsing = True -+ -+def getaddresses(fieldvalues, *, strict=True): -+ """Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue. -+ -+ When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in -+ its place. -+ -+ If strict is true, use a strict parser which rejects malformed inputs. -+ """ -+ -+ # 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 [('', -+ # '')] is returned in its place. This is done to avoid invalid output. -+ # -+ # Malformed input: getaddresses(['alice@example.com ']) -+ # Invalid output: [('', 'alice@example.com'), ('', 'bob@example.com')] -+ # Safe output: [('', '')] -+ -+ if not strict: -+ all = COMMASPACE.join(str(v) for v in fieldvalues) -+ a = _AddressList(all) -+ return a.addresslist -+ -+ fieldvalues = [str(v) for v in fieldvalues] -+ fieldvalues = _pre_parse_validation(fieldvalues) -+ addr = COMMASPACE.join(fieldvalues) -+ a = _AddressList(addr) -+ result = _post_parse_validation(a.addresslist) -+ -+ # Treat output as invalid if the number of addresses is not equal to the -+ # expected number of addresses. -+ n = 0 -+ for v in fieldvalues: -+ # When a comma is used in the Real Name part it is not a deliminator. -+ # So strip those out before counting the commas. -+ v = _strip_quoted_realnames(v) -+ # Expected number of addresses: 1 + number of commas -+ n += 1 + v.count(',') -+ if len(result) != n: -+ return [('', '')] -+ -+ return result -+ -+ -+def _check_parenthesis(addr): -+ # Ignore parenthesis in quoted real names. -+ addr = _strip_quoted_realnames(addr) -+ -+ opens = 0 -+ for pos, ch in _iter_escaped_chars(addr): -+ if ch == '(': -+ opens += 1 -+ elif ch == ')': -+ opens -= 1 -+ if opens < 0: -+ return False -+ return (opens == 0) -+ -+ -+def _pre_parse_validation(email_header_fields): -+ accepted_values = [] -+ for v in email_header_fields: -+ if not _check_parenthesis(v): -+ v = "('', '')" -+ accepted_values.append(v) -+ -+ return accepted_values -+ -+ -+def _post_parse_validation(parsed_email_header_tuples): -+ accepted_values = [] -+ # The parser would have parsed a correctly formatted domain-literal -+ # The existence of an [ after parsing indicates a parsing failure -+ for v in parsed_email_header_tuples: -+ if '[' in v[1]: -+ v = ('', '') -+ accepted_values.append(v) -+ -+ return accepted_values - - - def _format_timetuple_and_zone(timetuple, zone): -@@ -202,16 +318,33 @@ def parsedate_to_datetime(data): - tzinfo=datetime.timezone(datetime.timedelta(seconds=tz))) - - --def parseaddr(addr): -+def parseaddr(addr, *, strict=True): - """ - Parse addr into its constituent realname and email address parts. - - Return a tuple of realname and email address, unless the parse fails, in - which case return a 2-tuple of ('', ''). -+ -+ If strict is True, use a strict parser which rejects malformed inputs. - """ -- addrs = _AddressList(addr).addresslist -- if not addrs: -- return '', '' -+ if not strict: -+ addrs = _AddressList(addr).addresslist -+ if not addrs: -+ return ('', '') -+ return addrs[0] -+ -+ if isinstance(addr, list): -+ addr = addr[0] -+ -+ if not isinstance(addr, str): -+ return ('', '') -+ -+ addr = _pre_parse_validation([addr])[0] -+ addrs = _post_parse_validation(_AddressList(addr).addresslist) -+ -+ if not addrs or len(addrs) > 1: -+ return ('', '') -+ - return addrs[0] - - -diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py -index 761ea90b78..0c689643de 100644 ---- a/Lib/test/test_email/test_email.py -+++ b/Lib/test/test_email/test_email.py -@@ -16,6 +16,7 @@ from unittest.mock import patch - - import email - import email.policy -+import email.utils - - from email.charset import Charset - from email.header import Header, decode_header, make_header -@@ -3263,15 +3264,154 @@ Foo - [('Al Person', 'aperson@dom.ain'), - ('Bud Person', 'bperson@dom.ain')]) - -+ def test_getaddresses_comma_in_name(self): -+ """GH-106669 regression test.""" -+ self.assertEqual( -+ utils.getaddresses( -+ [ -+ '"Bud, Person" ', -+ 'aperson@dom.ain (Al Person)', -+ '"Mariusz Felisiak" ', -+ ] -+ ), -+ [ -+ ('Bud, Person', 'bperson@dom.ain'), -+ ('Al Person', 'aperson@dom.ain'), -+ ('Mariusz Felisiak', 'to@example.com'), -+ ], -+ ) -+ -+ def test_parsing_errors(self): -+ """Test for parsing errors from CVE-2023-27043 and CVE-2019-16056""" -+ alice = 'alice@example.org' -+ bob = 'bob@example.com' -+ empty = ('', '') -+ -+ # Test utils.getaddresses() and utils.parseaddr() on malformed email -+ # addresses: default behavior (strict=True) rejects malformed address, -+ # and strict=False which tolerates malformed address. -+ for invalid_separator, expected_non_strict in ( -+ ('(', [(f'<{bob}>', alice)]), -+ (')', [('', alice), empty, ('', bob)]), -+ ('<', [('', alice), empty, ('', bob), empty]), -+ ('>', [('', alice), empty, ('', bob)]), -+ ('[', [('', f'{alice}[<{bob}>]')]), -+ (']', [('', alice), empty, ('', bob)]), -+ ('@', [empty, empty, ('', bob)]), -+ (';', [('', alice), empty, ('', bob)]), -+ (':', [('', alice), ('', bob)]), -+ ('.', [('', alice + '.'), ('', bob)]), -+ ('"', [('', alice), ('', f'<{bob}>')]), -+ ): -+ address = f'{alice}{invalid_separator}<{bob}>' -+ with self.subTest(address=address): -+ self.assertEqual(utils.getaddresses([address]), -+ [empty]) -+ self.assertEqual(utils.getaddresses([address], strict=False), -+ expected_non_strict) -+ -+ self.assertEqual(utils.parseaddr([address]), -+ empty) -+ self.assertEqual(utils.parseaddr([address], strict=False), -+ ('', address)) -+ -+ # Comma (',') is treated differently depending on strict parameter. -+ # Comma without quotes. -+ address = f'{alice},<{bob}>' -+ self.assertEqual(utils.getaddresses([address]), -+ [('', alice), ('', bob)]) -+ self.assertEqual(utils.getaddresses([address], strict=False), -+ [('', alice), ('', bob)]) -+ self.assertEqual(utils.parseaddr([address]), -+ empty) -+ self.assertEqual(utils.parseaddr([address], strict=False), -+ ('', address)) -+ -+ # Real name between quotes containing comma. -+ address = '"Alice, alice@example.org" ' -+ expected_strict = ('Alice, alice@example.org', 'bob@example.com') -+ self.assertEqual(utils.getaddresses([address]), [expected_strict]) -+ self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict]) -+ self.assertEqual(utils.parseaddr([address]), expected_strict) -+ self.assertEqual(utils.parseaddr([address], strict=False), -+ ('', address)) -+ -+ # Valid parenthesis in comments. -+ address = 'alice@example.org (Alice)' -+ expected_strict = ('Alice', 'alice@example.org') -+ self.assertEqual(utils.getaddresses([address]), [expected_strict]) -+ self.assertEqual(utils.getaddresses([address], strict=False), [expected_strict]) -+ self.assertEqual(utils.parseaddr([address]), expected_strict) -+ self.assertEqual(utils.parseaddr([address], strict=False), -+ ('', address)) -+ -+ # Invalid parenthesis in comments. -+ address = 'alice@example.org )Alice(' -+ self.assertEqual(utils.getaddresses([address]), [empty]) -+ self.assertEqual(utils.getaddresses([address], strict=False), -+ [('', 'alice@example.org'), ('', ''), ('', 'Alice')]) -+ self.assertEqual(utils.parseaddr([address]), empty) -+ self.assertEqual(utils.parseaddr([address], strict=False), -+ ('', address)) -+ -+ # Two addresses with quotes separated by comma. -+ address = '"Jane Doe" , "John Doe" ' -+ self.assertEqual(utils.getaddresses([address]), -+ [('Jane Doe', 'jane@example.net'), -+ ('John Doe', 'john@example.net')]) -+ self.assertEqual(utils.getaddresses([address], strict=False), -+ [('Jane Doe', 'jane@example.net'), -+ ('John Doe', 'john@example.net')]) -+ self.assertEqual(utils.parseaddr([address]), empty) -+ self.assertEqual(utils.parseaddr([address], strict=False), -+ ('', address)) -+ -+ # Test email.utils.supports_strict_parsing attribute -+ self.assertEqual(email.utils.supports_strict_parsing, True) -+ - def test_getaddresses_nasty(self): -- eq = self.assertEqual -- eq(utils.getaddresses(['foo: ;']), [('', '')]) -- eq(utils.getaddresses( -- ['[]*-- =~$']), -- [('', ''), ('', ''), ('', '*--')]) -- eq(utils.getaddresses( -- ['foo: ;', '"Jason R. Mastaler" ']), -- [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]) -+ for addresses, expected in ( -+ (['"Sürname, Firstname" '], -+ [('Sürname, Firstname', 'to@example.com')]), -+ -+ (['foo: ;'], -+ [('', '')]), -+ -+ (['foo: ;', '"Jason R. Mastaler" '], -+ [('', ''), ('Jason R. Mastaler', 'jason@dom.ain')]), -+ -+ ([r'Pete(A nice \) chap) '], -+ [('Pete (A nice ) chap his account his host)', 'pete@silly.test')]), -+ -+ (['(Empty list)(start)Undisclosed recipients :(nobody(I know))'], -+ [('', '')]), -+ -+ (['Mary <@machine.tld:mary@example.net>, , jdoe@test . example'], -+ [('Mary', 'mary@example.net'), ('', ''), ('', 'jdoe@test.example')]), -+ -+ (['John Doe '], -+ [('John Doe (comment)', 'jdoe@machine.example')]), -+ -+ (['"Mary Smith: Personal Account" '], -+ [('Mary Smith: Personal Account', 'smith@home.example')]), -+ -+ (['Undisclosed recipients:;'], -+ [('', '')]), -+ -+ ([r', "Giant; \"Big\" Box" '], -+ [('', 'boss@nil.test'), ('Giant; "Big" Box', 'bob@example.net')]), -+ ): -+ with self.subTest(addresses=addresses): -+ self.assertEqual(utils.getaddresses(addresses), -+ expected) -+ self.assertEqual(utils.getaddresses(addresses, strict=False), -+ expected) -+ -+ addresses = ['[]*-- =~$'] -+ self.assertEqual(utils.getaddresses(addresses), -+ [('', '')]) -+ self.assertEqual(utils.getaddresses(addresses, strict=False), -+ [('', ''), ('', ''), ('', '*--')]) - - def test_getaddresses_embedded_comment(self): - """Test proper handling of a nested comment""" -@@ -3460,6 +3600,54 @@ multipart/report - m = cls(*constructor, policy=email.policy.default) - self.assertIs(m.policy, email.policy.default) - -+ def test_iter_escaped_chars(self): -+ self.assertEqual(list(utils._iter_escaped_chars(r'a\\b\"c\\"d')), -+ [(0, 'a'), -+ (2, '\\\\'), -+ (3, 'b'), -+ (5, '\\"'), -+ (6, 'c'), -+ (8, '\\\\'), -+ (9, '"'), -+ (10, 'd')]) -+ self.assertEqual(list(utils._iter_escaped_chars('a\\')), -+ [(0, 'a'), (1, '\\')]) -+ -+ def test_strip_quoted_realnames(self): -+ def check(addr, expected): -+ self.assertEqual(utils._strip_quoted_realnames(addr), expected) -+ -+ check('"Jane Doe" , "John Doe" ', -+ ' , ') -+ check(r'"Jane \"Doe\"." ', -+ ' ') -+ -+ # special cases -+ check(r'before"name"after', 'beforeafter') -+ check(r'before"name"', 'before') -+ check(r'b"name"', 'b') # single char -+ check(r'"name"after', 'after') -+ check(r'"name"a', 'a') # single char -+ check(r'"name"', '') -+ -+ # no change -+ for addr in ( -+ 'Jane Doe , John Doe ', -+ 'lone " quote', -+ ): -+ self.assertEqual(utils._strip_quoted_realnames(addr), addr) -+ -+ -+ def test_check_parenthesis(self): -+ addr = 'alice@example.net' -+ self.assertTrue(utils._check_parenthesis(f'{addr} (Alice)')) -+ self.assertFalse(utils._check_parenthesis(f'{addr} )Alice(')) -+ self.assertFalse(utils._check_parenthesis(f'{addr} (Alice))')) -+ self.assertFalse(utils._check_parenthesis(f'{addr} ((Alice)')) -+ -+ # Ignore real name between quotes -+ self.assertTrue(utils._check_parenthesis(f'")Alice((" {addr}')) -+ - - # Test the iterator/generators - class TestIterators(TestEmailBase): -diff --git a/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst b/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst -new file mode 100644 -index 0000000000..3d0e9e4078 ---- /dev/null -+++ b/Misc/NEWS.d/next/Library/2023-10-20-15-28-08.gh-issue-102988.dStNO7.rst -@@ -0,0 +1,8 @@ -+:func:`email.utils.getaddresses` and :func:`email.utils.parseaddr` now -+return ``('', '')`` 2-tuples in more situations where invalid email -+addresses are encountered instead of potentially inaccurate values. Add -+optional *strict* parameter to these two functions: use ``strict=False`` to -+get the old behavior, accept malformed inputs. -+``getattr(email.utils, 'supports_strict_parsing', False)`` can be use to check -+if the *strict* paramater is available. Patch by Thomas Dwyer and Victor -+Stinner to improve the CVE-2023-27043 fix. diff --git a/00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch b/00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch deleted file mode 100644 index ce6c9f4..0000000 --- a/00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= -Date: Tue, 5 Dec 2023 21:02:06 +0100 -Subject: [PATCH] 00419: gh-112769: test_zlib: Fix comparison of - ZLIB_RUNTIME_VERSION with non-int suffix (GH-112771) (GH-112774) - -zlib-ng defines the version as "1.3.0.zlib-ng". -(cherry picked from commit d384813ff18b33280a90b6d2011654528a2b6ad1) ---- - Lib/test/test_zlib.py | 28 ++++++++++++++++------------ - 1 file changed, 16 insertions(+), 12 deletions(-) - -diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py -index 02509cdf55..2a9e7e5ed3 100644 ---- a/Lib/test/test_zlib.py -+++ b/Lib/test/test_zlib.py -@@ -17,6 +17,20 @@ requires_Decompress_copy = unittest.skipUnless( - 'requires Decompress.copy()') - - -+def _zlib_runtime_version_tuple(zlib_version=zlib.ZLIB_RUNTIME_VERSION): -+ # Register "1.2.3" as "1.2.3.0" -+ # or "1.2.0-linux","1.2.0.f","1.2.0.f-linux" -+ v = zlib_version.split('-', 1)[0].split('.') -+ if len(v) < 4: -+ v.append('0') -+ elif not v[-1].isnumeric(): -+ v[-1] = '0' -+ return tuple(map(int, v)) -+ -+ -+ZLIB_RUNTIME_VERSION_TUPLE = _zlib_runtime_version_tuple() -+ -+ - class VersionTestCase(unittest.TestCase): - - def test_library_version(self): -@@ -437,9 +451,8 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): - sync_opt = ['Z_NO_FLUSH', 'Z_SYNC_FLUSH', 'Z_FULL_FLUSH', - 'Z_PARTIAL_FLUSH'] - -- ver = tuple(int(v) for v in zlib.ZLIB_RUNTIME_VERSION.split('.')) - # Z_BLOCK has a known failure prior to 1.2.5.3 -- if ver >= (1, 2, 5, 3): -+ if ZLIB_RUNTIME_VERSION_TUPLE >= (1, 2, 5, 3): - sync_opt.append('Z_BLOCK') - - sync_opt = [getattr(zlib, opt) for opt in sync_opt -@@ -768,16 +781,7 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): - - def test_wbits(self): - # wbits=0 only supported since zlib v1.2.3.5 -- # Register "1.2.3" as "1.2.3.0" -- # or "1.2.0-linux","1.2.0.f","1.2.0.f-linux" -- v = zlib.ZLIB_RUNTIME_VERSION.split('-', 1)[0].split('.') -- if len(v) < 4: -- v.append('0') -- elif not v[-1].isnumeric(): -- v[-1] = '0' -- -- v = tuple(map(int, v)) -- supports_wbits_0 = v >= (1, 2, 3, 5) -+ supports_wbits_0 = ZLIB_RUNTIME_VERSION_TUPLE >= (1, 2, 3, 5) - - co = zlib.compressobj(level=1, wbits=15) - zlib15 = co.compress(HAMLET_SCENE) + co.flush() diff --git a/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch b/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch new file mode 100644 index 0000000..a8e849e --- /dev/null +++ b/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch @@ -0,0 +1,51 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Mon, 31 Mar 2025 20:29:04 +0200 +Subject: 00452: Properly apply exported CFLAGS for dtrace/systemtap builds + +When using --with-dtrace the resulting object file could be missing +specific CFLAGS exported by the build system due to the systemtap +script using specific defaults. + +Exporting the CC and CFLAGS variables before the dtrace invocation +allows us to properly apply CFLAGS exported by the build system +even when cross-compiling. + +Co-authored-by: stratakis +--- + Makefile.pre.in | 4 ++-- + .../next/Build/2025-03-31-19-22-41.gh-issue-131865.PIJy7X.rst | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + create mode 100644 Misc/NEWS.d/next/Build/2025-03-31-19-22-41.gh-issue-131865.PIJy7X.rst + +diff --git a/Makefile.pre.in b/Makefile.pre.in +index 568018827b..b401724d92 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -989,7 +989,7 @@ Python/frozen.o: $(srcdir)/Python/importlib.h $(srcdir)/Python/importlib_externa + # an include guard, so we can't use a pipeline to transform its output. + Include/pydtrace_probes.h: $(srcdir)/Include/pydtrace.d + $(MKDIR_P) Include +- $(DTRACE) $(DFLAGS) -o $@ -h -s $< ++ CC="$(CC)" CFLAGS="$(CFLAGS)" $(DTRACE) $(DFLAGS) -o $@ -h -s $< + : sed in-place edit with POSIX-only tools + sed 's/PYTHON_/PyDTrace_/' $@ > $@.tmp + mv $@.tmp $@ +@@ -999,7 +999,7 @@ Python/import.o: $(srcdir)/Include/pydtrace.h + Modules/gcmodule.o: $(srcdir)/Include/pydtrace.h + + Python/pydtrace.o: $(srcdir)/Include/pydtrace.d $(DTRACE_DEPS) +- $(DTRACE) $(DFLAGS) -o $@ -G -s $< $(DTRACE_DEPS) ++ CC="$(CC)" CFLAGS="$(CFLAGS)" $(DTRACE) $(DFLAGS) -o $@ -G -s $< $(DTRACE_DEPS) + + Objects/typeobject.o: Objects/typeslots.inc + +diff --git a/Misc/NEWS.d/next/Build/2025-03-31-19-22-41.gh-issue-131865.PIJy7X.rst b/Misc/NEWS.d/next/Build/2025-03-31-19-22-41.gh-issue-131865.PIJy7X.rst +new file mode 100644 +index 0000000000..a287e0b228 +--- /dev/null ++++ b/Misc/NEWS.d/next/Build/2025-03-31-19-22-41.gh-issue-131865.PIJy7X.rst +@@ -0,0 +1,2 @@ ++The DTrace build now properly passes the ``CC`` and ``CFLAGS`` variables ++to the ``dtrace`` command when utilizing SystemTap on Linux. diff --git a/00471-cve-2025-12084.patch b/00471-cve-2025-12084.patch new file mode 100644 index 0000000..78c49fd --- /dev/null +++ b/00471-cve-2025-12084.patch @@ -0,0 +1,140 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Mon, 22 Dec 2025 14:48:49 +0100 +Subject: 00471: CVE-2025-12084 + +* gh-142145: Remove quadratic behavior in node ID cache clearing (GH-142146) +* gh-142754: Ensure that Element & Attr instances have the ownerDocument attribute (GH-142794) +(cherry picked from commit 1cc7551b3f9f71efbc88d96dce90f82de98b2454) +(cherry picked from commit 08d8e18ad81cd45bc4a27d6da478b51ea49486e4) +(cherry picked from commit 8d2d7bb2e754f8649a68ce4116271a4932f76907) + +Co-authored-by: Jacob Walls <38668450+jacobtylerwalls@users.noreply.github.com> +Co-authored-by: Seth Michael Larson +Co-authored-by: Petr Viktorin +Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> +Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> +Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> +Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> +Co-authored-by: Gregory P. Smith +--- + Lib/test/test_minidom.py | 33 ++++++++++++++++++- + Lib/xml/dom/minidom.py | 11 ++----- + ...-12-01-09-36-45.gh-issue-142145.tcAUhg.rst | 6 ++++ + 3 files changed, 41 insertions(+), 9 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst + +diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py +index 97620258d8..9f7f5b240e 100644 +--- a/Lib/test/test_minidom.py ++++ b/Lib/test/test_minidom.py +@@ -2,6 +2,7 @@ + + import copy + import pickle ++import time + import io + from test import support + import unittest +@@ -9,7 +10,7 @@ import unittest + import pyexpat + import xml.dom.minidom + +-from xml.dom.minidom import parse, Node, Document, parseString ++from xml.dom.minidom import parse, Attr, Node, Document, Element, parseString + from xml.dom.minidom import getDOMImplementation + from xml.parsers.expat import ExpatError + +@@ -163,6 +164,36 @@ class MinidomTest(unittest.TestCase): + self.confirm(dom.documentElement.childNodes[-1].data == "Hello") + dom.unlink() + ++ @support.requires_resource('cpu') ++ def testAppendChildNoQuadraticComplexity(self): ++ impl = getDOMImplementation() ++ ++ newdoc = impl.createDocument(None, "some_tag", None) ++ top_element = newdoc.documentElement ++ children = [newdoc.createElement(f"child-{i}") for i in range(1, 2 ** 15 + 1)] ++ element = top_element ++ ++ start = time.monotonic() ++ for child in children: ++ element.appendChild(child) ++ element = child ++ end = time.monotonic() ++ ++ # This example used to take at least 30 seconds. ++ # Conservative assertion due to the wide variety of systems and ++ # build configs timing based tests wind up run under. ++ # A --with-address-sanitizer --with-pydebug build on a rpi5 still ++ # completes this loop in <0.5 seconds. ++ self.assertLess(end - start, 4) ++ ++ def testSetAttributeNodeWithoutOwnerDocument(self): ++ # regression test for gh-142754 ++ elem = Element("test") ++ attr = Attr("id") ++ attr.value = "test-id" ++ elem.setAttributeNode(attr) ++ self.assertEqual(elem.getAttribute("id"), "test-id") ++ + def testAppendChildFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.appendChild(frag) +diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py +index d09ef5e7d0..e4e8b42996 100644 +--- a/Lib/xml/dom/minidom.py ++++ b/Lib/xml/dom/minidom.py +@@ -292,13 +292,6 @@ def _append_child(self, node): + childNodes.append(node) + node.parentNode = self + +-def _in_document(node): +- # return True iff node is part of a document tree +- while node is not None: +- if node.nodeType == Node.DOCUMENT_NODE: +- return True +- node = node.parentNode +- return False + + def _write_data(writer, data): + "Writes datachars to writer." +@@ -355,6 +348,7 @@ class Attr(Node): + def __init__(self, qName, namespaceURI=EMPTY_NAMESPACE, localName=None, + prefix=None): + self.ownerElement = None ++ self.ownerDocument = None + self._name = qName + self.namespaceURI = namespaceURI + self._prefix = prefix +@@ -678,6 +672,7 @@ class Element(Node): + + def __init__(self, tagName, namespaceURI=EMPTY_NAMESPACE, prefix=None, + localName=None): ++ self.ownerDocument = None + self.parentNode = None + self.tagName = self.nodeName = tagName + self.prefix = prefix +@@ -1537,7 +1532,7 @@ def _clear_id_cache(node): + if node.nodeType == Node.DOCUMENT_NODE: + node._id_cache.clear() + node._id_search_stack = None +- elif _in_document(node): ++ elif node.ownerDocument: + node.ownerDocument._id_cache.clear() + node.ownerDocument._id_search_stack= None + +diff --git a/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst +new file mode 100644 +index 0000000000..05c7df35d1 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2025-12-01-09-36-45.gh-issue-142145.tcAUhg.rst +@@ -0,0 +1,6 @@ ++Remove quadratic behavior in ``xml.minidom`` node ID cache clearing. In order ++to do this without breaking existing users, we also add the *ownerDocument* ++attribute to :mod:`xml.dom.minidom` elements and attributes created by directly ++instantiating the ``Element`` or ``Attr`` class. Note that this way of creating ++nodes is not supported; creator functions like ++:py:meth:`xml.dom.Document.documentElement` should be used instead. diff --git a/plan.fmf b/plan.fmf new file mode 100644 index 0000000..f5f58a3 --- /dev/null +++ b/plan.fmf @@ -0,0 +1,50 @@ +execute: + how: tmt + +provision: + hardware: + memory: '>= 3 GB' + +environment: + pybasever: '3.9' + +discover: + - name: tests_python + how: shell + url: https://src.fedoraproject.org/tests/python.git + tests: + - name: smoke + path: /smoke + test: "VERSION=${pybasever} ./venv.sh" + - name: debugsmoke + path: /smoke + test: "PYTHON=python${pybasever}d TOX=false VERSION=${pybasever} INSTALL_OR_SKIP=true ./venv.sh" + - name: selftest + path: /selftest + test: VERSION=${pybasever} X="-x test_wsgiref" ./parallel.sh + - name: marshalparser + path: /marshalparser + test: "VERSION=${pybasever} SAMPLE=10 ./test_marshalparser_compatibility.sh" + +prepare: + - name: Install dependencies + how: install + package: + - gcc # for extension building in venv and selftest + - gdb # for test_gdb + - "python${pybasever}" # the test subject + - "python${pybasever}-devel" # for extension building in venv and selftest + - "python${pybasever}-tkinter" # for selftest + - "python${pybasever}-test" # for selftest + - python3-tox # for venv tests + - glibc-all-langpacks # for locale tests + - marshalparser # for testing compatibility (magic numbers) with marshalparser + - rpm # for debugging marshalparser + - dnf # for upgrade + - name: Update packages + how: shell + script: dnf upgrade -y + - name: rpm_qa + order: 100 + how: shell + script: rpm -qa | sort | tee $TMT_PLAN_DATA/rpmqa.txt diff --git a/python3.9.spec b/python3.9.spec index 3a2e159..751cd07 100644 --- a/python3.9.spec +++ b/python3.9.spec @@ -13,11 +13,11 @@ URL: https://www.python.org/ # WARNING When rebasing to a new Python version, # remember to update the python3-docs package as well -%global general_version %{pybasever}.19 +%global general_version %{pybasever}.25 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -40,9 +40,10 @@ License: Python %endif # Flat package, i.e. no separate subpackages -# Default (in Fedora): if this is a main Python, it is not a flatpackage +# Default (in Fedora >= 44): disabled +# Default (in Fedora < 44): enabled when this is not the main Python # Not supported: Combination of flatpackage enabled and main_python enabled -%if %{with main_python} +%if %{with main_python} || 0%{?fedora} >= 44 %bcond_with flatpackage %else %bcond_without flatpackage @@ -237,6 +238,7 @@ BuildRequires: libnsl2-devel BuildRequires: libtirpc-devel BuildRequires: libGL-devel BuildRequires: libuuid-devel +BuildRequires: libxcrypt-devel BuildRequires: libX11-devel BuildRequires: make BuildRequires: ncurses-devel @@ -249,9 +251,9 @@ BuildRequires: sqlite-devel BuildRequires: gdb BuildRequires: tar -BuildRequires: tcl-devel +BuildRequires: tcl-devel < 1:9 BuildRequires: tix-devel -BuildRequires: tk-devel +BuildRequires: tk-devel < 1:9 BuildRequires: tzdata %if %{with valgrind} @@ -261,6 +263,7 @@ BuildRequires: valgrind-devel BuildRequires: xz-devel BuildRequires: zlib-devel +BuildRequires: systemtap-sdt-devel BuildRequires: /usr/bin/dtrace # workaround http://bugs.python.org/issue19804 (test_uuid requires ifconfig) @@ -269,6 +272,9 @@ BuildRequires: /usr/sbin/ifconfig %if %{with rpmwheels} BuildRequires: python-setuptools-wheel BuildRequires: python-pip-wheel +%else +# For %%python_wheel_inject_sbom +BuildRequires: python-rpm-macros %endif %if %{without bootstrap} @@ -301,6 +307,7 @@ Source11: idle3.appdata.xml # 00001 # d06a8853cf4bae9e115f45e1d531d2dc152c5cc8 # Fixup distutils/unixccompiler.py to remove standard library path from rpath +# # Was Patch0 in ivazquez' python3000 specfile Patch1: 00001-rpath.patch @@ -312,7 +319,7 @@ Patch1: 00001-rpath.patch # See https://bugzilla.redhat.com/show_bug.cgi?id=556092 Patch111: 00111-no-static-lib.patch -# 00189 # 60517f098bd1525ad454adf7252b60a3d6b0f8ba +# 00189 # 0c6dd5d318a22bbe89e09e1cd5513eaaca549aa5 # Instead of bundled wheels, use our RPM packaged wheels # # We keep them in /usr/share/python-wheels @@ -325,7 +332,7 @@ Patch189: 00189-use-rpm-wheels.patch # When the bundled setuptools/pip wheel is updated, the patch no longer applies cleanly. # In such cases, the patch needs to be amended and the versions updated here: %global pip_version 23.0.1 -%global setuptools_version 58.1.0 +%global setuptools_version 79.0.1 # 00251 # 1b1047c14ff98eae6d355b4aac4df3e388813f62 # Change user install location @@ -384,20 +391,24 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # gh-99086: Fix implicit int compiler warning in configure check for PTHREAD_SCOPE_SYSTEM Patch407: 00407-gh-99086-fix-implicit-int-compiler-warning-in-configure-check-for-pthread_scope_system.patch -# 00415 # 512c60eb23a8d7b26d74824a6d7bbefb6feefb65 -# [CVE-2023-27043] gh-102988: Reject malformed addresses in email.parseaddr() (#111116) +# 00452 # eb11d070c5af7d1b5e47f4e02186152d08eaf793 +# Properly apply exported CFLAGS for dtrace/systemtap builds # -# 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. -Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch +# When using --with-dtrace the resulting object file could be missing +# specific CFLAGS exported by the build system due to the systemtap +# script using specific defaults. +# +# Exporting the CC and CFLAGS variables before the dtrace invocation +# allows us to properly apply CFLAGS exported by the build system +# even when cross-compiling. +Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch -# 00419 # f13682530cc7e4daec2e40acd56508846fdd3aad -# gh-112769: test_zlib: Fix comparison of ZLIB_RUNTIME_VERSION with non-int suffix (GH-112771) (GH-112774) +# 00471 # fc5f344f7e15c13dbf41824a1b7a82d92205f79d +# CVE-2025-12084 # -# zlib-ng defines the version as "1.3.0.zlib-ng". -Patch419: 00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch +# * 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 # (New patches go here ^^^) # @@ -467,9 +478,18 @@ Obsoletes: platform-python < %{pybasever} Provides: python%{pyshortver} = %{version}-%{release} Obsoletes: python%{pyshortver} < %{version}-%{release} +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: %{pkgname} < 3.9.24-2 + +%if %{with main_python} # Packages with Python modules in standard locations automatically # depend on python(abi). Provide that here. Provides: python(abi) = %{pybasever} +%else +# We exclude the `python(abi)` Provides +%global __requires_exclude ^python\\(abi\\) = 3\\..+ +%global __provides_exclude ^python\\(abi\\) = 3\\..+ +%endif Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} @@ -584,6 +604,8 @@ Conflicts: python-libs < 3 # (We explicitly conflict with python-libs and not python2-libs, so only the # old Python 2 builds that still provided unversioned Python are handled.) +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: %{pkgname} < 3.9.24-2 %description -n %{pkgname}-libs This package contains runtime libraries for use by Python: @@ -603,6 +625,7 @@ Requires: (python3-rpm-macros if rpm-build) Requires: (pyproject-rpm-macros if rpm-build) %if %{without bootstrap} +%if %{with main_python} # This is not "API" (packages that need setuptools should still BuildRequire it) # However some packages apparently can build both with and without setuptools # producing egg-info as file or directory (depending on setuptools presence). @@ -611,6 +634,7 @@ Requires: (pyproject-rpm-macros if rpm-build) # See https://bugzilla.redhat.com/show_bug.cgi?id=1623914 # See https://fedoraproject.org/wiki/Packaging:Directory_Replacement Requires: (%{pkgname}-setuptools if rpm-build) +%endif Requires: (python3-rpm-generators if rpm-build) %endif @@ -630,6 +654,9 @@ Provides: platform-python-devel%{?_isa} = %{version}-%{release} Obsoletes: platform-python-devel < %{pybasever} %endif +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: %{pkgname} < 3.9.24-2 + %description -n %{pkgname}-devel This package contains the header files and configuration needed to compile Python extension modules (typically written in C or C++), to embed Python @@ -654,6 +681,9 @@ Obsoletes: %{pkgname}-tools < %{version}-%{release} # In Fedora 31, /usr/bin/idle was moved here from Python 2. Conflicts: python-tools < 3 +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: %{pkgname} < 3.9.24-2 + %description -n %{pkgname}-idle IDLE is Python’s Integrated Development and Learning Environment. @@ -675,6 +705,9 @@ Requires: %{pkgname} = %{version}-%{release} # (We don't provide python3-turtledemo, that's not too useful when imported.) %py_provides %{pkgname}-turtle +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: %{pkgname} < 3.9.24-2 + %description -n %{pkgname}-tkinter The Tkinter (Tk interface) library is a graphical user interface toolkit for the Python programming language. @@ -685,6 +718,9 @@ Summary: The self-test suite for the main python3 package Requires: %{pkgname} = %{version}-%{release} Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} +# https://docs.fedoraproject.org/en-US/packaging-guidelines/#_one_to_many_replacement +Obsoletes: %{pkgname} < 3.9.24-2 + %description -n %{pkgname}-test The self-test suite for the Python interpreter. @@ -735,11 +771,6 @@ The debug runtime additionally supports debug builds of C-API extensions %else # with flatpackage -# We'll not provide this, on purpose -# No package in Fedora shall ever depend on flatpackage via this -%global __requires_exclude ^python\\(abi\\) = 3\\..$ -%global __provides_exclude ^python\\(abi\\) = 3\\..$ - # Python interpreter packages used to be named (or provide) name pythonXY (e.g. # python39). However, to align it with the executable names and to prepare for # Python 3.10, they were renamed to pythonX.Y (e.g. python3.9, python3.10). We @@ -772,6 +803,16 @@ Requires: tzdata # Other subpackages (like -debug) also need this, but they all depend on -libs. Requires: expat >= 2.6 +# Provides of the subpackages contained in flatpackage +Provides: %{pkgname}-libs = %{version}-%{release} +Provides: %{pkgname}-devel = %{version}-%{release} +Provides: %{pkgname}-idle = %{version}-%{release} +Provides: %{pkgname}-tkinter = %{version}-%{release} +Provides: %{pkgname}-test = %{version}-%{release} +%if %{with debug_build} +Provides: %{pkgname}-debug = %{version}-%{release} +%endif + # The description for the flat package (SRPM and built) %description Python %{pybasever} package for developers. @@ -1228,6 +1269,11 @@ for file in %{buildroot}%{pylibdir}/pydoc_data/topics.py $(grep --include='*.py' rm ${directory}/{__pycache__/${module}.cpython-%{pyshortver}.opt-?.pyc,${module}.py} done +%if %{without rpmwheels} +# Inject SBOM into the installed wheels (if the macro is available) +%{?python_wheel_inject_sbom:%python_wheel_inject_sbom %{buildroot}%{pylibdir}/ensurepip/_bundled/*.whl} +%endif + # ====================================================== # Checks for packaging issues # ====================================================== @@ -1298,6 +1344,8 @@ CheckPython() { # package: rpmbuild requires /usr/bin/pythonX.Y to be installed # test_gdb on arm on Fedora 33: # https://bugzilla.redhat.com/show_bug.cgi?id=1846390 + # test_sendfile_close_peer_in_the_middle_of_receiving: + # https://github.com/python/cpython/issues/120226 LD_LIBRARY_PATH=$ConfDir $ConfDir/python -m test.regrtest \ -wW --slowest -j0 --timeout=1800 \ %if %{with bootstrap} @@ -1311,6 +1359,9 @@ CheckPython() { -x test_gdb \ %endif %endif + %ifarch ppc64le + -i test_sendfile_close_peer_in_the_middle_of_receiving \ + %endif echo FINISHED: CHECKING OF PYTHON FOR CONFIGURATION: $ConfName @@ -1490,6 +1541,10 @@ CheckPython optimized %dir %{pylibdir}/site-packages/ %dir %{pylibdir}/site-packages/__pycache__/ %{pylibdir}/site-packages/README.txt + +%exclude %{pylibdir}/_sysconfigdata_d_linux_%{platform_triplet}.py +%exclude %{pylibdir}/__pycache__/_sysconfigdata_d_linux_%{platform_triplet}%{bytecode_suffixes} + %{pylibdir}/*.py %dir %{pylibdir}/__pycache__/ %{pylibdir}/__pycache__/*%{bytecode_suffixes} @@ -1818,6 +1873,9 @@ CheckPython optimized %{dynload_dir}/_testinternalcapi.%{SOABI_debug}.so %{dynload_dir}/_testmultiphase.%{SOABI_debug}.so +%{pylibdir}/_sysconfigdata_d_linux_%{platform_triplet}.py +%{pylibdir}/__pycache__/_sysconfigdata_d_linux_%{platform_triplet}%{bytecode_suffixes} + %endif # with debug_build # We put the debug-gdb.py file inside /usr/lib/debug to avoid noise from ldconfig @@ -1841,6 +1899,69 @@ CheckPython optimized # ====================================================== %changelog +* Wed Jan 14 2026 Lumír Balhar - 3.9.25-3 +- Security fix for CVE-2025-12084 + +* Mon Nov 10 2025 Tomas Orsava - 3.9.25-2 +- Move _sysconfigdata_d_linux*.py to the debug subpackage + +* Mon Nov 03 2025 Karolina Surma - 3.9.25-1 +- Update to Python 3.9.25 + +* Wed Oct 15 2025 Miro Hrončok - 3.9.24-2 +- On Fedora 44+, split this package into multiple subpackages +- This mimics newer Python versions + +* Fri Oct 10 2025 Karolina Surma - 3.9.24-1 +- Update to Python 3.9.24 + +* Fri Jul 25 2025 Fedora Release Engineering - 3.9.23-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Wed Jun 04 2025 Tomáš Hrnčiar - 3.9.23-1 +- Update to 3.9.23 + +* Wed Apr 23 2025 Miro Hrončok - 3.9.22-2 +- Add RPM Provides for python3.9-libs, python3.9-devel, python3.9-idle, python3.9-tkinter, python3.9-test + +* Wed Apr 09 2025 Tomáš Hrnčiar - 3.9.22-1 +- Update to 3.9.22 + +* Mon Mar 31 2025 Charalampos Stratakis - 3.9.21-5 +- Properly apply exported CFLAGS for dtrace/systemtap builds +- Fixes: rhbz#2356304 + +* Mon Feb 10 2025 Charalampos Stratakis - 3.9.21-4 +- Security fix for CVE-2025-0938 +- Fixes: rhbz#2343278 + +* Sat Feb 01 2025 Björn Esser - 3.9.21-3 +- Add explicit BR: libxcrypt-devel + +* Sat Jan 18 2025 Fedora Release Engineering - 3.9.21-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + +* Tue Dec 03 2024 Lumír Balhar - 3.9.21-1 +- Update to 3.9.21 +- Fixes: rhbz#2321662 + +* Mon Sep 09 2024 Tomáš Hrnčiar - 3.9.20-1 +- Update to 3.9.20 + +* Fri Aug 23 2024 Charalampos Stratakis - 3.9.19-6 +- Security fix for CVE-2024-8088 +- Fixes: rhbz#2307466 + +* Tue Aug 13 2024 Lumír Balhar - 3.9.19-5 +- Security fix for CVE-2024-4032 (rhbz#2293397) +- Security fix for CVE-2024-6923 (rhbz#2303164) + +* Tue Jul 23 2024 Lumír Balhar - 3.9.19-4 +- Require systemtap-sdt-devel for sys/sdt.h + +* Fri Jul 19 2024 Fedora Release Engineering - 3.9.19-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Wed Apr 17 2024 Miro Hrončok - 3.9.19-2 - Require expat >= 2.6 to prevent errors when creating venvs with older expat diff --git a/sources b/sources index be10285..8a5f37e 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.9.19.tar.xz) = 5577830c734e63a70bbc62cd33d263b9aa87c4381b49cb694c3559067c4c682a55506b65ec5514a8e0a5abf6294dc728e909385d449ae1c388e62f83cea9bb89 -SHA512 (Python-3.9.19.tar.xz.asc) = f7f4946243dfc56de2c84f50276b088d347f17054f50e3331d1e312e2a8e2c6ed1b4b4a807202b51137fd2af3fc9218cafa42ed348a954ace896d9a432e2defd +SHA512 (Python-3.9.25.tar.xz) = 33fd65952cc3ce5df83825aa32a103935815bdd5a016e5fd9896cafb068a3f89b3a6134458a2694e4f0f4f8a9fbe84739b53116264728b32cde0f03ab210cb19 +SHA512 (Python-3.9.25.tar.xz.asc) = 83f0a0e558aa89a106bdffeeb9b0fa2685fbd7be5c5954f9176c59c6c7023716207b07239f202b3508cbb98ca34572161955f0bfd3732fdb9265721cd6723dbe diff --git a/tests/provision.fmf b/tests/provision.fmf deleted file mode 100644 index 1a4f0f0..0000000 --- a/tests/provision.fmf +++ /dev/null @@ -1,4 +0,0 @@ ---- -standard-inventory-qcow2: - qemu: - m: 3G # Amount of VM memory diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 027091f..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,37 +0,0 @@ ---- -- hosts: localhost - tags: - - classic - tasks: - - dnf: - name: "*" - state: latest - -- hosts: localhost - roles: - - role: standard-test-basic - tags: - - classic - repositories: - - repo: "https://src.fedoraproject.org/tests/python.git" - dest: "python" - tests: - - rpm_qa: - run: rpm -qa - - smoke: - dir: python/smoke - run: VERSION=3.9 ./venv.sh - - selftest: - dir: python/selftest - run: VERSION=3.9 X="-x test_wsgiref" ./parallel.sh - - marshalparser: - dir: python/marshalparser - run: VERSION=3.9 SAMPLE=10 test_marshalparser_compatibility.sh - required_packages: - - gcc # for extension building in venv and selftest - - gdb # for test_gdb - - python3.9 # the test subject - - python3-tox # for venv tests - - glibc-all-langpacks # for locale tests - - marshalparser # for testing compatibility (magic numbers) with marshalparser - - rpm # for debugging