diff --git a/00001-rpath.patch b/00001-rpath.patch index cd063e5..778c077 100644 --- a/00001-rpath.patch +++ b/00001-rpath.patch @@ -1,10 +1,9 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 13 Jan 2010 21:25:18 +0000 -Subject: 00001: Fixup distutils/unixccompiler.py to remove standard library - path from rpath +Subject: [PATCH] 00001: Fixup distutils/unixccompiler.py to remove standard + library path from rpath Was Patch0 in ivazquez' python3000 specfile -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 bdabed8..37966be 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: 00111: Don't try to build a libpythonMAJOR.MINOR.a +Subject: [PATCH] 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 322da15..dfb47f4 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: 00189: Instead of bundled wheels, use our RPM packaged wheels +Subject: [PATCH] 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 d61bb089e3..77d7ec5a65 100644 +index 07065c3cb7..77d7ec5a65 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -1,3 +1,5 @@ @@ -30,7 +30,7 @@ index d61bb089e3..77d7ec5a65 100644 __all__ = ["version", "bootstrap"] --_SETUPTOOLS_VERSION = "79.0.1" +-_SETUPTOOLS_VERSION = "58.1.0" -_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 ecceb6c..f961419 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: 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 diff --git a/00353-architecture-names-upstream-downstream.patch b/00353-architecture-names-upstream-downstream.patch index 343ff96..b0b955c 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: 00353: Original names for architectures with different names +Subject: [PATCH] 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 747e55d..c089771 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: 00371: Revert "bpo-1596321: Fix threading._shutdown() for the main - thread (GH-28549) (GH-28589)" +Subject: [PATCH] 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 4df365e..0c63a32 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: 00407: gh-99086: Fix implicit int compiler warning in configure check - for PTHREAD_SCOPE_SYSTEM +Subject: [PATCH] 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 new file mode 100644 index 0000000..af44881 --- /dev/null +++ b/00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch @@ -0,0 +1,500 @@ +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 new file mode 100644 index 0000000..ce6c9f4 --- /dev/null +++ b/00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch @@ -0,0 +1,66 @@ +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 deleted file mode 100644 index a8e849e..0000000 --- a/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch +++ /dev/null @@ -1,51 +0,0 @@ -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 deleted file mode 100644 index 78c49fd..0000000 --- a/00471-cve-2025-12084.patch +++ /dev/null @@ -1,140 +0,0 @@ -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 deleted file mode 100644 index f5f58a3..0000000 --- a/plan.fmf +++ /dev/null @@ -1,50 +0,0 @@ -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 751cd07..3a2e159 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}.25 +%global general_version %{pybasever}.19 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 2%{?dist} License: Python @@ -40,10 +40,9 @@ License: Python %endif # Flat package, i.e. no separate subpackages -# Default (in Fedora >= 44): disabled -# Default (in Fedora < 44): enabled when this is not the main Python +# Default (in Fedora): if this is a main Python, it is not a flatpackage # Not supported: Combination of flatpackage enabled and main_python enabled -%if %{with main_python} || 0%{?fedora} >= 44 +%if %{with main_python} %bcond_with flatpackage %else %bcond_without flatpackage @@ -238,7 +237,6 @@ BuildRequires: libnsl2-devel BuildRequires: libtirpc-devel BuildRequires: libGL-devel BuildRequires: libuuid-devel -BuildRequires: libxcrypt-devel BuildRequires: libX11-devel BuildRequires: make BuildRequires: ncurses-devel @@ -251,9 +249,9 @@ BuildRequires: sqlite-devel BuildRequires: gdb BuildRequires: tar -BuildRequires: tcl-devel < 1:9 +BuildRequires: tcl-devel BuildRequires: tix-devel -BuildRequires: tk-devel < 1:9 +BuildRequires: tk-devel BuildRequires: tzdata %if %{with valgrind} @@ -263,7 +261,6 @@ 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) @@ -272,9 +269,6 @@ 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} @@ -307,7 +301,6 @@ 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 @@ -319,7 +312,7 @@ Patch1: 00001-rpath.patch # See https://bugzilla.redhat.com/show_bug.cgi?id=556092 Patch111: 00111-no-static-lib.patch -# 00189 # 0c6dd5d318a22bbe89e09e1cd5513eaaca549aa5 +# 00189 # 60517f098bd1525ad454adf7252b60a3d6b0f8ba # Instead of bundled wheels, use our RPM packaged wheels # # We keep them in /usr/share/python-wheels @@ -332,7 +325,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 79.0.1 +%global setuptools_version 58.1.0 # 00251 # 1b1047c14ff98eae6d355b4aac4df3e388813f62 # Change user install location @@ -391,24 +384,20 @@ 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 -# 00452 # eb11d070c5af7d1b5e47f4e02186152d08eaf793 -# Properly apply exported CFLAGS for dtrace/systemtap builds +# 00415 # 512c60eb23a8d7b26d74824a6d7bbefb6feefb65 +# [CVE-2023-27043] gh-102988: Reject malformed addresses in email.parseaddr() (#111116) # -# 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 +# 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 -# 00471 # fc5f344f7e15c13dbf41824a1b7a82d92205f79d -# CVE-2025-12084 +# 00419 # f13682530cc7e4daec2e40acd56508846fdd3aad +# gh-112769: test_zlib: Fix comparison of ZLIB_RUNTIME_VERSION with non-int suffix (GH-112771) (GH-112774) # -# * 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 +# 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 # (New patches go here ^^^) # @@ -478,18 +467,9 @@ 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} @@ -604,8 +584,6 @@ 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: @@ -625,7 +603,6 @@ 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). @@ -634,7 +611,6 @@ 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 @@ -654,9 +630,6 @@ 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 @@ -681,9 +654,6 @@ 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. @@ -705,9 +675,6 @@ 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. @@ -718,9 +685,6 @@ 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. @@ -771,6 +735,11 @@ 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 @@ -803,16 +772,6 @@ 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. @@ -1269,11 +1228,6 @@ 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 # ====================================================== @@ -1344,8 +1298,6 @@ 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} @@ -1359,9 +1311,6 @@ 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 @@ -1541,10 +1490,6 @@ 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} @@ -1873,9 +1818,6 @@ 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 @@ -1899,69 +1841,6 @@ 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 8a5f37e..be10285 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.9.25.tar.xz) = 33fd65952cc3ce5df83825aa32a103935815bdd5a016e5fd9896cafb068a3f89b3a6134458a2694e4f0f4f8a9fbe84739b53116264728b32cde0f03ab210cb19 -SHA512 (Python-3.9.25.tar.xz.asc) = 83f0a0e558aa89a106bdffeeb9b0fa2685fbd7be5c5954f9176c59c6c7023716207b07239f202b3508cbb98ca34572161955f0bfd3732fdb9265721cd6723dbe +SHA512 (Python-3.9.19.tar.xz) = 5577830c734e63a70bbc62cd33d263b9aa87c4381b49cb694c3559067c4c682a55506b65ec5514a8e0a5abf6294dc728e909385d449ae1c388e62f83cea9bb89 +SHA512 (Python-3.9.19.tar.xz.asc) = f7f4946243dfc56de2c84f50276b088d347f17054f50e3331d1e312e2a8e2c6ed1b4b4a807202b51137fd2af3fc9218cafa42ed348a954ace896d9a432e2defd diff --git a/.fmf/version b/tests/.fmf/version similarity index 100% rename from .fmf/version rename to tests/.fmf/version diff --git a/tests/provision.fmf b/tests/provision.fmf new file mode 100644 index 0000000..1a4f0f0 --- /dev/null +++ b/tests/provision.fmf @@ -0,0 +1,4 @@ +--- +standard-inventory-qcow2: + qemu: + m: 3G # Amount of VM memory diff --git a/tests/tests.yml b/tests/tests.yml new file mode 100644 index 0000000..027091f --- /dev/null +++ b/tests/tests.yml @@ -0,0 +1,37 @@ +--- +- 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