From dd49c3369d578f91fc1b9901cb216c821c8b8ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 25 May 2021 00:56:32 +0200 Subject: [PATCH 001/112] Fedora CI: Make the marshalparser dependency mandatory Fedora 32 goes EOL and marshalparser is available on Fedora 33+. --- tests/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tests.yml b/tests/tests.yml index 1af5868..a3eb1b2 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -24,10 +24,11 @@ run: VERSION=3.10 X="" ./parallel.sh - marshalparser: dir: python/marshalparser - run: INSTALL_OR_SKIP=true VERSION=3.10 SAMPLE=10 test_marshalparser_compatibility.sh + run: VERSION=3.10 SAMPLE=10 test_marshalparser_compatibility.sh required_packages: - gcc # for extension building in venv and selftest - gdb # for test_gdb - python3.10 - python3-tox # for venv tests - glibc-all-langpacks # for locale tests + - marshalparser # for testing compatibility (magic numbers) with marshalparser From da277b0c4e600ad4b96809f1130865295117b019 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Fri, 14 May 2021 14:46:08 +0200 Subject: [PATCH 002/112] Use the system installed mpdecimal instead of the bundled copy (#1943359) --- python3.10.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 6ebed67..9972b33 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ %global prerel b1 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -197,6 +197,7 @@ BuildRequires: libGL-devel BuildRequires: libuuid-devel BuildRequires: libX11-devel BuildRequires: make +BuildRequires: mpdecimal-devel BuildRequires: ncurses-devel BuildRequires: openssl-devel @@ -610,6 +611,7 @@ find -name '*.exe' -print -delete # Remove bundled libraries to ensure that we're using the system copy. rm -r Modules/expat +rm -r Modules/_decimal/libmpdec # Remove files that should be generated by the build # (This is after patching, so that we can use patches directly from upstream) @@ -695,6 +697,7 @@ BuildPython() { --with-dbmliborder=gdbm:ndbm:bdb \ --with-system-expat \ --with-system-ffi \ + --with-system-libmpdec \ --enable-loadable-sqlite-extensions \ --with-dtrace \ --with-lto \ @@ -1575,6 +1578,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri May 14 2021 Charalampos Stratakis - 3.10.0~b1-2 +- Use the system installed mpdecimal instead of the bundled copy (#1943359) + * Tue May 04 2021 Tomas Hrnciar - 3.10.0~b1-1 - Update to 3.10.0b1 From ee4998146281b01f84f7001572dbd75342d14e51 Mon Sep 17 00:00:00 2001 From: Tomas Hrnciar Date: Tue, 1 Jun 2021 13:41:14 +0200 Subject: [PATCH 003/112] Update to 3.10.0b2 --- 00251-change-user-install-location.patch | 4 ++-- 00328-pyc-timestamp-invalidation-mode.patch | 2 +- python3.10.spec | 7 +++++-- sources | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index 15aead0..e9ea32d 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -15,10 +15,10 @@ Downstream only: Awaiting resources to work on upstream PEP 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py -index d33a889afe..41c6165cd8 100644 +index 26696cfb9d..1826cbcb38 100644 --- a/Lib/distutils/command/install.py +++ b/Lib/distutils/command/install.py -@@ -431,8 +431,19 @@ def finalize_unix(self): +@@ -441,8 +441,19 @@ def finalize_unix(self): raise DistutilsOptionError( "must not supply exec-prefix without prefix") diff --git a/00328-pyc-timestamp-invalidation-mode.patch b/00328-pyc-timestamp-invalidation-mode.patch index 011e0f6..138868e 100644 --- a/00328-pyc-timestamp-invalidation-mode.patch +++ b/00328-pyc-timestamp-invalidation-mode.patch @@ -33,7 +33,7 @@ index 0f9b59025c..59dc3fe50b 100644 else: return PycInvalidationMode.TIMESTAMP diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py -index b58f28a4bc..7ede33d6c9 100644 +index 5ed98dbff1..f30c4e43de 100644 --- a/Lib/test/test_py_compile.py +++ b/Lib/test/test_py_compile.py @@ -19,6 +19,7 @@ def without_source_date_epoch(fxn): diff --git a/python3.10.spec b/python3.10.spec index 9972b33..d1cba9a 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -14,10 +14,10 @@ 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}.0 -%global prerel b1 +%global prerel b2 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python @@ -1578,6 +1578,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Jun 01 2021 Tomas Hrnciar - 3.10.0~b2-1 +- Update to 3.10.0b2 + * Fri May 14 2021 Charalampos Stratakis - 3.10.0~b1-2 - Use the system installed mpdecimal instead of the bundled copy (#1943359) diff --git a/sources b/sources index 89085d0..470f37f 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0b1.tar.xz) = b8366f1fd92690bf78dc8ce07724d1b79a8c7f246e9a13ba3043687c5553b52d4d7baf48bf96f9fe088de73baef1df2131e2704ffed9a7549890723a7898c4c5 -SHA512 (Python-3.10.0b1.tar.xz.asc) = 7e22dd9ddf37d0c2116cfb9f08050f0909ccc04f1a63e67b96f0cec743845c492659a661af518fd76d513fa36d08da11fe3a1166ede31de583369b4c3389de57 +SHA512 (Python-3.10.0b2.tar.xz) = ace86ef11608fbb016d0b8efc7d20cccede4663cd09f07a07e067530537b1e4989379a6c18e7aa9b86b87b108d65efedc39eaf946d27df6ea474a829c763ebdd +SHA512 (Python-3.10.0b2.tar.xz.asc) = 9a84ab98a5215f13302c7a983e9224096d15c07d9a7899b28daff49405c46efdf7770263ca57e6e0f85ce1cbc0cafec373baf1675ade6ddb0eb268e99753907d From bc9e36d400cb0b43c51944cddb4aa89a5db67438 Mon Sep 17 00:00:00 2001 From: Python Maint Date: Tue, 1 Jun 2021 16:09:23 +0200 Subject: [PATCH 004/112] Bootstrap for Python 3.10 --- python3.10.spec | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index d1cba9a..bfcec8d 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -1,3 +1,7 @@ +%global _without_optimizations 1 +%global _without_tests 1 +%global _without_rpmwheels 1 +%global _with_bootstrap 1 # ================== # Top-level metadata # ================== @@ -17,7 +21,7 @@ URL: https://www.python.org/ %global prerel b2 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -1578,6 +1582,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Jun 01 2021 Python Maint - 3.10.0~b2-2 +- Bootstrap for Python 3.10 + * Tue Jun 01 2021 Tomas Hrnciar - 3.10.0~b2-1 - Update to 3.10.0b2 From b8586120e5f70b903adb941a84917244477c740c Mon Sep 17 00:00:00 2001 From: Python Maint Date: Tue, 1 Jun 2021 16:53:08 +0200 Subject: [PATCH 005/112] Rebuilt for Python 3.10 --- python3.10.spec | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index bfcec8d..175f572 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -1,7 +1,3 @@ -%global _without_optimizations 1 -%global _without_tests 1 -%global _without_rpmwheels 1 -%global _with_bootstrap 1 # ================== # Top-level metadata # ================== @@ -21,7 +17,7 @@ URL: https://www.python.org/ %global prerel b2 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -1582,6 +1578,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Jun 01 2021 Python Maint - 3.10.0~b2-3 +- Rebuilt for Python 3.10 + * Tue Jun 01 2021 Python Maint - 3.10.0~b2-2 - Bootstrap for Python 3.10 From 51d9e334afdd261291969ec6dc401c243d36aabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 18 Jun 2021 01:17:19 +0200 Subject: [PATCH 006/112] Update to 3.10.0b3 --- ...importlib-test_entry_points_by_index.patch | 36 +++++++++++++++++++ python3.10.spec | 15 ++++++-- sources | 4 +-- 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch diff --git a/00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch b/00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch new file mode 100644 index 0000000..62feb1c --- /dev/null +++ b/00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch @@ -0,0 +1,36 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= +Date: Fri, 18 Jun 2021 15:16:04 +0200 +Subject: [PATCH] 00363: Reset DeprecationWarning filters in + test_importlib.test_entry_points_by_index + +This avoids StopIteration error when running tests. + +https://bugs.python.org/issue44451 +--- + Lib/test/test_importlib/test_metadata_api.py | 1 + + .../NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst | 3 +++ + 2 files changed, 4 insertions(+) + create mode 100644 Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst + +diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py +index 3506493463..2bfc44b18e 100644 +--- a/Lib/test/test_importlib/test_metadata_api.py ++++ b/Lib/test/test_importlib/test_metadata_api.py +@@ -139,6 +139,7 @@ def test_entry_points_by_index(self): + """ + eps = distribution('distinfo-pkg').entry_points + with warnings.catch_warnings(record=True) as caught: ++ warnings.filterwarnings("default", category=DeprecationWarning) + eps[0] + + # check warning +diff --git a/Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst b/Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst +new file mode 100644 +index 0000000000..0f635cfe18 +--- /dev/null ++++ b/Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst +@@ -0,0 +1,3 @@ ++Reset ``DeprecationWarning`` filters in ++``test.test_importlib.test_metadata_api.APITests.test_entry_points_by_index`` ++to avoid ``StopIteration`` error if ``DeprecationWarnings`` are ignored. diff --git a/python3.10.spec b/python3.10.spec index 175f572..7bd28a1 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -14,10 +14,10 @@ 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}.0 -%global prerel b2 +%global prerel b3 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python @@ -292,6 +292,14 @@ Patch251: 00251-change-user-install-location.patch # Ideally, we should talk to upstream and explain why we don't want this Patch328: 00328-pyc-timestamp-invalidation-mode.patch +# 00363 # bcb4a805ad54d3a810fb54582e67c5f5fe6d9773 +# Reset DeprecationWarning filters in test_importlib.test_entry_points_by_index +# +# This avoids StopIteration error when running tests. +# +# https://bugs.python.org/issue44451 +Patch363: 00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1578,6 +1586,9 @@ CheckPython optimized # ====================================================== %changelog +* Thu Jun 17 2021 Miro Hrončok - 3.10.0~b3-1 +- Update to 3.10.0b3 + * Tue Jun 01 2021 Python Maint - 3.10.0~b2-3 - Rebuilt for Python 3.10 diff --git a/sources b/sources index 470f37f..ef907d3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0b2.tar.xz) = ace86ef11608fbb016d0b8efc7d20cccede4663cd09f07a07e067530537b1e4989379a6c18e7aa9b86b87b108d65efedc39eaf946d27df6ea474a829c763ebdd -SHA512 (Python-3.10.0b2.tar.xz.asc) = 9a84ab98a5215f13302c7a983e9224096d15c07d9a7899b28daff49405c46efdf7770263ca57e6e0f85ce1cbc0cafec373baf1675ade6ddb0eb268e99753907d +SHA512 (Python-3.10.0b3.tar.xz) = ef0dc5eddb5f9702ab88faa2827455347caa81ab6c03192d6e37c968a40c53ab485d5c923905c511d19bc35e10129aa302f6733e0a7d296da8f725367dd1b258 +SHA512 (Python-3.10.0b3.tar.xz.asc) = 6b8d2caf753f0d92019e18d1441e323a44aff06ee8bdc272572a67359dc4bece833db56b9318c91962d39ee4d09bf701b548d71ae02c4b64f3c21f1c23ed1d36 From d85cc76235dc0c0840199d43fbcf2bfbdd45c2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 8 Jun 2021 16:13:40 +0200 Subject: [PATCH 007/112] Fedora CI: This is now the main Python --- tests/tests.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/tests.yml b/tests/tests.yml index a3eb1b2..ddd375e 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -19,16 +19,29 @@ - smoke: dir: python/smoke run: VERSION=3.10 ./venv.sh + - debugsmoke: + dir: python/smoke + run: PYTHON=python3-debug TOX=false VERSION=3.10 ./venv.sh - selftest: dir: python/selftest run: VERSION=3.10 X="" ./parallel.sh + - debugtest: + dir: python/selftest + run: VERSION=3.10 PYTHON=python3-debug X="" ./parallel.sh + - debugflags: + dir: python/flags + run: python3-debug ./assertflags.py -O0 - marshalparser: dir: python/marshalparser run: VERSION=3.10 SAMPLE=10 test_marshalparser_compatibility.sh required_packages: - gcc # for extension building in venv and selftest - gdb # for test_gdb - - python3.10 + - python3.10 # the test subject + - python3-debug # for leak testing + - python3-devel # for extension building in venv and selftest + - python3-tkinter # for selftest + - python3-test # for selftest - python3-tox # for venv tests - glibc-all-langpacks # for locale tests - marshalparser # for testing compatibility (magic numbers) with marshalparser From 943f8cc201eebf62e23203740dd79c19f7e3de32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 9 Jun 2021 15:01:00 +0200 Subject: [PATCH 008/112] Fedora CI: Add rpm -qa output for debugging --- tests/tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/tests.yml b/tests/tests.yml index ddd375e..4819891 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -16,6 +16,8 @@ - repo: "https://src.fedoraproject.org/tests/python.git" dest: "python" tests: + - rpm_qa: + run: rpm -qa - smoke: dir: python/smoke run: VERSION=3.10 ./venv.sh @@ -45,3 +47,4 @@ - python3-tox # for venv tests - glibc-all-langpacks # for locale tests - marshalparser # for testing compatibility (magic numbers) with marshalparser + - rpm # for debugging From 08bde6d5c85171fe6a27628094a4b61017e3d7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 12 Jul 2021 00:27:27 +0200 Subject: [PATCH 009/112] Update to 3.10.0b4 - patch 363 was a backport - bundled pip was updated to 21.1.3 --- ...importlib-test_entry_points_by_index.patch | 36 ------------------- python3.10.spec | 15 +++----- sources | 4 +-- 3 files changed, 7 insertions(+), 48 deletions(-) delete mode 100644 00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch diff --git a/00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch b/00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch deleted file mode 100644 index 62feb1c..0000000 --- a/00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= -Date: Fri, 18 Jun 2021 15:16:04 +0200 -Subject: [PATCH] 00363: Reset DeprecationWarning filters in - test_importlib.test_entry_points_by_index - -This avoids StopIteration error when running tests. - -https://bugs.python.org/issue44451 ---- - Lib/test/test_importlib/test_metadata_api.py | 1 + - .../NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst | 3 +++ - 2 files changed, 4 insertions(+) - create mode 100644 Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst - -diff --git a/Lib/test/test_importlib/test_metadata_api.py b/Lib/test/test_importlib/test_metadata_api.py -index 3506493463..2bfc44b18e 100644 ---- a/Lib/test/test_importlib/test_metadata_api.py -+++ b/Lib/test/test_importlib/test_metadata_api.py -@@ -139,6 +139,7 @@ def test_entry_points_by_index(self): - """ - eps = distribution('distinfo-pkg').entry_points - with warnings.catch_warnings(record=True) as caught: -+ warnings.filterwarnings("default", category=DeprecationWarning) - eps[0] - - # check warning -diff --git a/Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst b/Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst -new file mode 100644 -index 0000000000..0f635cfe18 ---- /dev/null -+++ b/Misc/NEWS.d/next/Tests/2021-06-18-15-19-35.bpo-44451.aj5pqE.rst -@@ -0,0 +1,3 @@ -+Reset ``DeprecationWarning`` filters in -+``test.test_importlib.test_metadata_api.APITests.test_entry_points_by_index`` -+to avoid ``StopIteration`` error if ``DeprecationWarnings`` are ignored. diff --git a/python3.10.spec b/python3.10.spec index 7bd28a1..fd29dad 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -14,7 +14,7 @@ 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}.0 -%global prerel b3 +%global prerel b4 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} Release: 1%{?dist} @@ -68,7 +68,7 @@ License: Python # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 21.1.1 +%global pip_version 21.1.3 %global setuptools_version 56.0.0 # Expensive optimizations (mainly, profile-guided optimizations) @@ -292,14 +292,6 @@ Patch251: 00251-change-user-install-location.patch # Ideally, we should talk to upstream and explain why we don't want this Patch328: 00328-pyc-timestamp-invalidation-mode.patch -# 00363 # bcb4a805ad54d3a810fb54582e67c5f5fe6d9773 -# Reset DeprecationWarning filters in test_importlib.test_entry_points_by_index -# -# This avoids StopIteration error when running tests. -# -# https://bugs.python.org/issue44451 -Patch363: 00363-reset-deprecationwarning-filters-in-test_importlib-test_entry_points_by_index.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1586,6 +1578,9 @@ CheckPython optimized # ====================================================== %changelog +* Sun Jul 11 2021 Miro Hrončok - 3.10.0~b4-1 +- Update to 3.10.0b4 + * Thu Jun 17 2021 Miro Hrončok - 3.10.0~b3-1 - Update to 3.10.0b3 diff --git a/sources b/sources index ef907d3..9fc0481 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0b3.tar.xz) = ef0dc5eddb5f9702ab88faa2827455347caa81ab6c03192d6e37c968a40c53ab485d5c923905c511d19bc35e10129aa302f6733e0a7d296da8f725367dd1b258 -SHA512 (Python-3.10.0b3.tar.xz.asc) = 6b8d2caf753f0d92019e18d1441e323a44aff06ee8bdc272572a67359dc4bece833db56b9318c91962d39ee4d09bf701b548d71ae02c4b64f3c21f1c23ed1d36 +SHA512 (Python-3.10.0b4.tar.xz) = deb5ce510c381ce7fcdc7056754b3afccdbc4610cb77b85115859a5e636065584f517e0931a31f77723c09229b2fd751011b1cf16967c075f629018f0a7975a4 +SHA512 (Python-3.10.0b4.tar.xz.asc) = 55ef4265d9217f35e5f1da3b8b560f711c3f118230ff5fb7fe3ab5e189c22c331cecb9783465234ac0df8a1e075887b5fedfbc181cab6e571e5e2f8403d9720d From 9d4a52895364bed09ebbc1339523bfa6d6e2767e Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 30 Jun 2021 12:50:32 +0200 Subject: [PATCH 010/112] Provide python3-turtle from python3-tkinter Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1952565 --- python3.10.spec | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index fd29dad..3528710 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ %global prerel b4 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -504,6 +504,10 @@ configuration, browsers, and other dialogs. Summary: A GUI toolkit for Python Requires: %{pkgname} = %{version}-%{release} +# The importable module "turtle" is here, so provide python3-turtle. +# (We don't provide python3-turtledemo, that's not too useful when imported.) +%py_provides %{pkgname}-turtle + %description -n %{pkgname}-tkinter The Tkinter (Tk interface) library is a graphical user interface toolkit for the Python programming language. @@ -1578,6 +1582,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jul 16 2021 Petr Viktorin - 3.10.0~b4-2 +- Provide python3-turtle from python3-tkinter + * Sun Jul 11 2021 Miro Hrončok - 3.10.0~b4-1 - Update to 3.10.0b4 From d2d07f0ea7f6f7a1ccc34ab90abe22598ee382db Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 15 Jul 2021 10:58:21 +0200 Subject: [PATCH 011/112] Require pyproject-rpm-macros from python3-devel Part of the new Python packaging guidelines change: - https://fedoraproject.org/wiki/Changes/PythonPackagingGuidelines202x - https://bugzilla.redhat.com/show_bug.cgi?id=1977883 --- python3.10.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index 3528710..c43b002 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -453,6 +453,7 @@ Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} # But we want them when packages BuildRequire python3-devel Requires: (python-rpm-macros if rpm-build) Requires: (python3-rpm-macros if rpm-build) +Requires: (pyproject-rpm-macros if rpm-build) # Python developers are very likely to need pip Recommends: %{pkgname}-pip @@ -1584,6 +1585,7 @@ CheckPython optimized %changelog * Fri Jul 16 2021 Petr Viktorin - 3.10.0~b4-2 - Provide python3-turtle from python3-tkinter +- Require pyproject-rpm-macros from python3-devel * Sun Jul 11 2021 Miro Hrončok - 3.10.0~b4-1 - Update to 3.10.0b4 From 7cf9a3a8cda3c4f3dcb7be722098af5a06cd2e20 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 23 Jul 2021 10:31:38 +0000 Subject: [PATCH 012/112] - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index c43b002..ceabda5 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ %global prerel b4 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -1583,6 +1583,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jul 23 2021 Fedora Release Engineering - 3.10.0~b4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + * Fri Jul 16 2021 Petr Viktorin - 3.10.0~b4-2 - Provide python3-turtle from python3-tkinter - Require pyproject-rpm-macros from python3-devel From bda63fb917fd8fc2d0425beaae20800332daa588 Mon Sep 17 00:00:00 2001 From: Tomas Hrnciar Date: Tue, 3 Aug 2021 19:05:29 +0200 Subject: [PATCH 013/112] Update to 3.10.0rc1 --- python3.10.spec | 7 +++++-- sources | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index ceabda5..3fc06de 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -14,10 +14,10 @@ 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}.0 -%global prerel b4 +%global prerel rc1 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python @@ -1583,6 +1583,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Aug 03 2021 Tomas Hrnciar - 3.10.0~rc1-1 +- Update to 3.10.0rc1 + * Fri Jul 23 2021 Fedora Release Engineering - 3.10.0~b4-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild diff --git a/sources b/sources index 9fc0481..bfe876d 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0b4.tar.xz) = deb5ce510c381ce7fcdc7056754b3afccdbc4610cb77b85115859a5e636065584f517e0931a31f77723c09229b2fd751011b1cf16967c075f629018f0a7975a4 -SHA512 (Python-3.10.0b4.tar.xz.asc) = 55ef4265d9217f35e5f1da3b8b560f711c3f118230ff5fb7fe3ab5e189c22c331cecb9783465234ac0df8a1e075887b5fedfbc181cab6e571e5e2f8403d9720d +SHA512 (Python-3.10.0rc1.tar.xz) = 917c26dade7ee366ae5a39e55b6a66eaef52271be77abba9b4145557e1d97eeb753e2dbe7cc52b8aba9c038fc041055faa66525875111bd449636045a0345932 +SHA512 (Python-3.10.0rc1.tar.xz.asc) = 3b82e3549878b0399e0560683c70e08b43750c788add11286144cf283f1485d450c8be872d05d9b86a438c58184b7a81d0fb70e0353705e42aa08213938ef936 From 19e0804a72f76f5660093ef6ee71077510ea1980 Mon Sep 17 00:00:00 2001 From: Tomas Hrnciar Date: Wed, 8 Sep 2021 11:21:16 +0200 Subject: [PATCH 014/112] Update to 3.10.0rc2 --- ...est_sysconfig-for-posix_user-platlib.patch | 58 +++++++++++++++++++ python3.10.spec | 16 ++++- sources | 4 +- 3 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch diff --git a/00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch b/00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch new file mode 100644 index 0000000..bacdd9e --- /dev/null +++ b/00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch @@ -0,0 +1,58 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Stinner +Date: Thu, 9 Sep 2021 11:02:48 +0200 +Subject: [PATCH] 00367: bpo-44860: Update test_sysconfig for posix_user + platlib + +Update test_sysconfig.test_user_similar() for the posix_user scheme: +"platlib" doesn't use sys.platlibdir. +--- + Lib/test/pythoninfo.py | 1 + + Lib/test/test_sysconfig.py | 12 +++++++++++- + .../Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst | 2 ++ + 3 files changed, 14 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst + +diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py +index 278dfe7f7d..39ee9e1d76 100644 +--- a/Lib/test/pythoninfo.py ++++ b/Lib/test/pythoninfo.py +@@ -96,6 +96,7 @@ def collect_sys(info_add): + 'maxunicode', + 'path', + 'platform', ++ 'platlibdir', + 'prefix', + 'thread_info', + 'version', +diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py +index b8b9add36d..9408657c91 100644 +--- a/Lib/test/test_sysconfig.py ++++ b/Lib/test/test_sysconfig.py +@@ -296,7 +296,17 @@ def test_user_similar(self): + base = base.replace(sys.base_prefix, sys.prefix) + if HAS_USER_BASE: + user_path = get_path(name, 'posix_user') +- self.assertEqual(user_path, global_path.replace(base, user, 1)) ++ expected = global_path.replace(base, user, 1) ++ # bpo-44860: platlib of posix_user doesn't use sys.platlibdir, ++ # whereas posix_prefix does. ++ if name == 'platlib': ++ # Replace "/lib64/python3.11/site-packages" suffix ++ # with "/lib/python3.11/site-packages". ++ py_version_short = sysconfig.get_python_version() ++ suffix = f'python{py_version_short}/site-packages' ++ expected = expected.replace(f'/{sys.platlibdir}/{suffix}', ++ f'/lib/{suffix}') ++ self.assertEqual(user_path, expected) + + def test_main(self): + # just making sure _main() runs and returns things in the stdout +diff --git a/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst b/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst +new file mode 100644 +index 0000000000..153a9c5573 +--- /dev/null ++++ b/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst +@@ -0,0 +1,2 @@ ++Update ``test_sysconfig.test_user_similar()`` for the posix_user scheme: ++``platlib`` doesn't use :data:`sys.platlibdir`. Patch by Victor Stinner. diff --git a/python3.10.spec b/python3.10.spec index 3fc06de..4832d70 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -14,7 +14,7 @@ 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}.0 -%global prerel rc1 +%global prerel rc2 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} Release: 1%{?dist} @@ -68,8 +68,8 @@ License: Python # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 21.1.3 -%global setuptools_version 56.0.0 +%global pip_version 21.2.3 +%global setuptools_version 57.4.0 # Expensive optimizations (mainly, profile-guided optimizations) %bcond_without optimizations @@ -292,6 +292,13 @@ Patch251: 00251-change-user-install-location.patch # Ideally, we should talk to upstream and explain why we don't want this Patch328: 00328-pyc-timestamp-invalidation-mode.patch +# 00367 # 35c53d99835a904129d2b0a86ad74aaf0ea78982 +# bpo-44860: Update test_sysconfig for posix_user platlib +# +# Update test_sysconfig.test_user_similar() for the posix_user scheme: +# "platlib" doesn't use sys.platlibdir. +Patch367: 00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1583,6 +1590,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Sep 08 2021 Tomas Hrnciar - 3.10.0~rc2-1 +- Update to 3.10.0rc2 + * Tue Aug 03 2021 Tomas Hrnciar - 3.10.0~rc1-1 - Update to 3.10.0rc1 diff --git a/sources b/sources index bfe876d..4f34baf 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0rc1.tar.xz) = 917c26dade7ee366ae5a39e55b6a66eaef52271be77abba9b4145557e1d97eeb753e2dbe7cc52b8aba9c038fc041055faa66525875111bd449636045a0345932 -SHA512 (Python-3.10.0rc1.tar.xz.asc) = 3b82e3549878b0399e0560683c70e08b43750c788add11286144cf283f1485d450c8be872d05d9b86a438c58184b7a81d0fb70e0353705e42aa08213938ef936 +SHA512 (Python-3.10.0rc2.tar.xz) = 8511d837e465818a7b41df4593f29179e4d420171a287deb484ab6834fe17fe6b9d49ea6ee619573c8fa02aae0bf11807b5fa5903b200e311a0ba27981ecdc04 +SHA512 (Python-3.10.0rc2.tar.xz.asc) = ce38167956314b27641f08fd5cad67bcf286154ff3a74a8987e9cda8b5737ed2218f0190726c7555cc5f49d76dee3d90521512e4560bfb4e91789217e36ee096 From 59e0a098f7370b5f5da8e40d65e33bf2191e67b8 Mon Sep 17 00:00:00 2001 From: Sahana Prasad Date: Tue, 14 Sep 2021 19:12:37 +0200 Subject: [PATCH 015/112] Rebuilt with OpenSSL 3.0.0 --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 4832d70..c9a6ddb 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ %global prerel rc2 %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -1590,6 +1590,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Sep 14 2021 Sahana Prasad - 3.10.0~rc2-2 +- Rebuilt with OpenSSL 3.0.0 + * Wed Sep 08 2021 Tomas Hrnciar - 3.10.0~rc2-1 - Update to 3.10.0rc2 From f2ba079270222adec232a0ca4efa690e3f69b02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 4 Oct 2021 21:25:03 +0200 Subject: [PATCH 016/112] Update to 3.10.0 final Patch 367 was included in this release. --- ...est_sysconfig-for-posix_user-platlib.patch | 58 ------------------- python3.10.spec | 14 ++--- sources | 4 +- 3 files changed, 7 insertions(+), 69 deletions(-) delete mode 100644 00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch diff --git a/00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch b/00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch deleted file mode 100644 index bacdd9e..0000000 --- a/00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Stinner -Date: Thu, 9 Sep 2021 11:02:48 +0200 -Subject: [PATCH] 00367: bpo-44860: Update test_sysconfig for posix_user - platlib - -Update test_sysconfig.test_user_similar() for the posix_user scheme: -"platlib" doesn't use sys.platlibdir. ---- - Lib/test/pythoninfo.py | 1 + - Lib/test/test_sysconfig.py | 12 +++++++++++- - .../Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst | 2 ++ - 3 files changed, 14 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst - -diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py -index 278dfe7f7d..39ee9e1d76 100644 ---- a/Lib/test/pythoninfo.py -+++ b/Lib/test/pythoninfo.py -@@ -96,6 +96,7 @@ def collect_sys(info_add): - 'maxunicode', - 'path', - 'platform', -+ 'platlibdir', - 'prefix', - 'thread_info', - 'version', -diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py -index b8b9add36d..9408657c91 100644 ---- a/Lib/test/test_sysconfig.py -+++ b/Lib/test/test_sysconfig.py -@@ -296,7 +296,17 @@ def test_user_similar(self): - base = base.replace(sys.base_prefix, sys.prefix) - if HAS_USER_BASE: - user_path = get_path(name, 'posix_user') -- self.assertEqual(user_path, global_path.replace(base, user, 1)) -+ expected = global_path.replace(base, user, 1) -+ # bpo-44860: platlib of posix_user doesn't use sys.platlibdir, -+ # whereas posix_prefix does. -+ if name == 'platlib': -+ # Replace "/lib64/python3.11/site-packages" suffix -+ # with "/lib/python3.11/site-packages". -+ py_version_short = sysconfig.get_python_version() -+ suffix = f'python{py_version_short}/site-packages' -+ expected = expected.replace(f'/{sys.platlibdir}/{suffix}', -+ f'/lib/{suffix}') -+ self.assertEqual(user_path, expected) - - def test_main(self): - # just making sure _main() runs and returns things in the stdout -diff --git a/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst b/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst -new file mode 100644 -index 0000000000..153a9c5573 ---- /dev/null -+++ b/Misc/NEWS.d/next/Tests/2021-09-08-13-01-37.bpo-44860.qXd0kx.rst -@@ -0,0 +1,2 @@ -+Update ``test_sysconfig.test_user_similar()`` for the posix_user scheme: -+``platlib`` doesn't use :data:`sys.platlibdir`. Patch by Victor Stinner. diff --git a/python3.10.spec b/python3.10.spec index c9a6ddb..8f3be9b 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -14,10 +14,10 @@ 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}.0 -%global prerel rc2 +#global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python @@ -292,13 +292,6 @@ Patch251: 00251-change-user-install-location.patch # Ideally, we should talk to upstream and explain why we don't want this Patch328: 00328-pyc-timestamp-invalidation-mode.patch -# 00367 # 35c53d99835a904129d2b0a86ad74aaf0ea78982 -# bpo-44860: Update test_sysconfig for posix_user platlib -# -# Update test_sysconfig.test_user_similar() for the posix_user scheme: -# "platlib" doesn't use sys.platlibdir. -Patch367: 00367-bpo-44860-update-test_sysconfig-for-posix_user-platlib.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1590,6 +1583,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Oct 04 2021 Miro Hrončok - 3.10.0-1 +- Update to 3.10.0 final + * Tue Sep 14 2021 Sahana Prasad - 3.10.0~rc2-2 - Rebuilt with OpenSSL 3.0.0 diff --git a/sources b/sources index 4f34baf..29a970b 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0rc2.tar.xz) = 8511d837e465818a7b41df4593f29179e4d420171a287deb484ab6834fe17fe6b9d49ea6ee619573c8fa02aae0bf11807b5fa5903b200e311a0ba27981ecdc04 -SHA512 (Python-3.10.0rc2.tar.xz.asc) = ce38167956314b27641f08fd5cad67bcf286154ff3a74a8987e9cda8b5737ed2218f0190726c7555cc5f49d76dee3d90521512e4560bfb4e91789217e36ee096 +SHA512 (Python-3.10.0.tar.xz) = 82b2729afc7d72a80882f199970667dce7d971a2e5ecfe6cf84f7b68612ab2caf6ed6d7a8cb81f24ea85cb0816464bb2e8b2e6884eda62fa40742edc674193bd +SHA512 (Python-3.10.0.tar.xz.asc) = 67236e02bc49da1423717cb54216b745f613ba2fc4b372a4aa15a36ab15fe69d9b9087070382957d480df7576d13056caedcd979fb56531799a1190b822f673d From 47935cfb9870804f77aaff8f93ace1d5e49bde94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 5 Oct 2021 11:53:19 +0200 Subject: [PATCH 017/112] Change the values of sysconfig's "posix_prefix" install scheme to /usr/local - when RPM build or venv/virtualenv is not detected - replaces the patch for distutils, as distutils is deprecated The original values are saved as an additional "rpm_prefix" install scheme. See https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/104 for a more detailed rationale. Downstream only for now, waiting for https://bugs.python.org/issue43976 --- 00251-change-user-install-location.patch | 112 +++++++++++++++-------- python3.10.spec | 36 ++++++-- 2 files changed, 104 insertions(+), 44 deletions(-) diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index e9ea32d..83c57ef 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -1,45 +1,33 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Michal Cyprian -Date: Mon, 26 Jun 2017 16:32:56 +0200 +From: Lumir Balhar +Date: Mon, 15 Feb 2021 12:19:27 +0100 Subject: [PATCH] 00251: Change user install location -Set values of prefix and exec_prefix in distutils install command -to /usr/local if executable is /usr/bin/python* and RPM build -is not detected to make pip and distutils install into separate location. +Change the values of sysconfig's "posix_prefix" install scheme to /usr/local +when RPM build or venv/virtualenv is not detected, +to make pip, sysconfig and distutils install into an isolated location. + +The original values are saved as an additional "rpm_prefix" install scheme. + +The site module adds the /usr/local paths to sys.path when site packages are +enabled and RPM build is not detected. Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe -Downstream only: Awaiting resources to work on upstream PEP ---- - Lib/distutils/command/install.py | 15 +++++++++++++-- - Lib/site.py | 9 ++++++++- - 2 files changed, 21 insertions(+), 3 deletions(-) -diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py -index 26696cfb9d..1826cbcb38 100644 ---- a/Lib/distutils/command/install.py -+++ b/Lib/distutils/command/install.py -@@ -441,8 +441,19 @@ def finalize_unix(self): - raise DistutilsOptionError( - "must not supply exec-prefix without prefix") - -- self.prefix = os.path.normpath(sys.prefix) -- self.exec_prefix = os.path.normpath(sys.exec_prefix) -+ # self.prefix is set to sys.prefix + /local/ -+ # if neither RPM build nor virtual environment is -+ # detected to make pip and distutils install packages -+ # into the separate location. -+ if (not (hasattr(sys, 'real_prefix') or -+ sys.prefix != sys.base_prefix) and -+ 'RPM_BUILD_ROOT' not in os.environ): -+ addition = "/local" -+ else: -+ addition = "" -+ -+ self.prefix = os.path.normpath(sys.prefix) + addition -+ self.exec_prefix = os.path.normpath(sys.exec_prefix) + addition - - else: - if self.exec_prefix is None: +Rewrote in Fedora 36+ to patch sysconfig instead of distutils, +see https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/104 + +Downstream only for now, waiting for https://bugs.python.org/issue43976 + +Co-authored-by: Petr Viktorin +Co-authored-by: Miro Hrončok +Co-authored-by: Michal Cyprian +--- + Lib/site.py | 9 ++++++++- + Lib/sysconfig.py | 19 +++++++++++++++++++ + Lib/test/test_sysconfig.py | 4 +++- + 3 files changed, 30 insertions(+), 2 deletions(-) + diff --git a/Lib/site.py b/Lib/site.py index 939893eb5e..d1316c3355 100644 --- a/Lib/site.py @@ -61,3 +49,55 @@ index 939893eb5e..d1316c3355 100644 for sitedir in getsitepackages(prefixes): if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) +diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py +index 95b48f6429..226b55a556 100644 +--- a/Lib/sysconfig.py ++++ b/Lib/sysconfig.py +@@ -58,6 +58,25 @@ + }, + } + ++# backup the original posix_prefix as rpm_prefix ++# RPM packages use it and we need to be able to read it even when changed ++_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix'] ++ ++if (not (hasattr(sys, 'real_prefix') or ++ sys.prefix != sys.base_prefix) and ++ 'RPM_BUILD_ROOT' not in os.environ): ++ _INSTALL_SCHEMES['posix_prefix'] = { ++ 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}', ++ 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}', ++ 'purelib': '{base}/local/lib/python{py_version_short}/site-packages', ++ 'platlib': '{platbase}/local/{platlibdir}/python{py_version_short}/site-packages', ++ 'include': ++ '{installed_base}/include/python{py_version_short}{abiflags}', ++ 'platinclude': ++ '{installed_platbase}/include/python{py_version_short}{abiflags}', ++ 'scripts': '{base}/local/bin', ++ 'data': '{base}/local', ++ } + + # NOTE: site.py has copy of this function. + # Sync it when modify this function. +diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py +index 9408657c91..db4cbc55ec 100644 +--- a/Lib/test/test_sysconfig.py ++++ b/Lib/test/test_sysconfig.py +@@ -263,7 +263,7 @@ def test_get_config_h_filename(self): + self.assertTrue(os.path.isfile(config_h), config_h) + + def test_get_scheme_names(self): +- wanted = ['nt', 'posix_home', 'posix_prefix'] ++ wanted = ['nt', 'posix_home', 'posix_prefix', 'rpm_prefix'] + if HAS_USER_BASE: + wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) + self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) +@@ -274,6 +274,8 @@ def test_symlink(self): # Issue 7880 + cmd = "-c", "import sysconfig; print(sysconfig.get_platform())" + self.assertEqual(py.call_real(*cmd), py.call_link(*cmd)) + ++ @unittest.skipIf('RPM_BUILD_ROOT' not in os.environ, ++ "Test doesn't expect Fedora's paths") + def test_user_similar(self): + # Issue #8759: make sure the posix scheme for the users + # is similar to the global posix_prefix one diff --git a/python3.10.spec b/python3.10.spec index 8f3be9b..5573db4 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -267,15 +267,24 @@ Source11: idle3.appdata.xml # Was Patch0 in ivazquez' python3000 specfile Patch1: 00001-rpath.patch -# 00251 # 5c445123f04d96be42a35eef5119378ba1713a96 +# 00251 # 0952e38e5bf725ebbab48b13a35566e30635ddf8 # Change user install location # -# Set values of prefix and exec_prefix in distutils install command -# to /usr/local if executable is /usr/bin/python* and RPM build -# is not detected to make pip and distutils install into separate location. +# Change the values of sysconfig's "posix_prefix" install scheme to /usr/local +# when RPM build or venv/virtualenv is not detected, +# to make pip, sysconfig and distutils install into an isolated location. +# +# The original values are saved as an additional "rpm_prefix" install scheme. +# +# The site module adds the /usr/local paths to sys.path when site packages are +# enabled and RPM build is not detected. # # Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe -# Downstream only: Awaiting resources to work on upstream PEP +# +# Rewrote in Fedora 36+ to patch sysconfig instead of distutils, +# see https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/104 +# +# Downstream only for now, waiting for https://bugs.python.org/issue43976 Patch251: 00251-change-user-install-location.patch # 00328 # 318e500c98f5e59eb1f23e0fcd32db69b9bd17e1 @@ -437,6 +446,10 @@ Recommends: (%{pkgname}-tkinter%{?_isa} = %{version}-%{release} if tk%{?_isa}) # The zoneinfo module needs tzdata Requires: tzdata +# Since patch 251 changed from distutils to sysconfig, pip needed to be adapted +# The previous versions could cause serious bugs during `sudo pip install --upgrade ...` +# Better safe than sorry +Conflicts: %{pkgname}-pip < 21.2.3-3 %description -n %{pkgname}-libs This package contains runtime libraries for use by Python: @@ -451,8 +464,10 @@ Requires: %{pkgname} = %{version}-%{release} Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} # The RPM related dependencies bring nothing to a non-RPM Python developer # But we want them when packages BuildRequire python3-devel -Requires: (python-rpm-macros if rpm-build) -Requires: (python3-rpm-macros if rpm-build) +# 3.10-9 macros started to set $RPM_BUILD_ROOT when expanding macros like %%python3_sitearch, +# which is necessary since patch 251 changed from distutils to sysconfig +Requires: (python-rpm-macros >= 3.10-9 if rpm-build) +Requires: (python3-rpm-macros >= 3.10-9 if rpm-build) Requires: (pyproject-rpm-macros if rpm-build) # Python developers are very likely to need pip @@ -1583,6 +1598,11 @@ CheckPython optimized # ====================================================== %changelog +* Tue Oct 05 2021 Miro Hrončok - 3.10.0-2 +- Change the values of sysconfig's "posix_prefix" install scheme to /usr/local + when RPM build or venv/virtualenv is not detected, + instead of patching distutils + * Mon Oct 04 2021 Miro Hrončok - 3.10.0-1 - Update to 3.10.0 final From d2c17b67d0cc63bcd8b8f8dadee1512625077f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Thu, 7 Oct 2021 07:30:41 +0200 Subject: [PATCH 018/112] Enable test_frozentable test_frozentable was disabled due to error in Python 3.10.0a6. This is now fixed so test can be enabled again. --- python3.10.spec | 2 -- 1 file changed, 2 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 5573db4..84dec96 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -1073,10 +1073,8 @@ CheckPython() { # test_distutils # distutils.tests.test_bdist_rpm tests fail when bootstraping the Python # package: rpmbuild requires /usr/bin/pythonX.Y to be installed - # test_frozentable fails with Python 3.10.0a6 (https://bugs.python.org/issue43372) LD_LIBRARY_PATH=$ConfDir $ConfDir/python -m test.regrtest \ -wW --slowest -j0 --timeout=1800 \ - -i test_frozentable \ %if %{with bootstrap} -x test_distutils \ %endif From 36ed4859ffc6dcc16b0319cac930cbabc82994b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 11 Oct 2021 13:13:50 +0200 Subject: [PATCH 019/112] Cosmetic CI config change: Use the new tox package name --- tests/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests.yml b/tests/tests.yml index 4819891..0da8e38 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -44,7 +44,7 @@ - python3-devel # for extension building in venv and selftest - python3-tkinter # for selftest - python3-test # for selftest - - python3-tox # for venv tests + - tox # for venv tests - glibc-all-langpacks # for locale tests - marshalparser # for testing compatibility (magic numbers) with marshalparser - rpm # for debugging From 4f08fc3037413ef5768cbde95000901c5fe3abe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 11 Oct 2021 13:14:41 +0200 Subject: [PATCH 020/112] Fedora CI: Also test virtualenv --- tests/tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/tests.yml b/tests/tests.yml index 0da8e38..c2f2df4 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -21,6 +21,9 @@ - smoke: dir: python/smoke run: VERSION=3.10 ./venv.sh + - smoke_virtualenv: + dir: python/smoke + run: VERSION=3.10 METHOD=virtualenv ./venv.sh - debugsmoke: dir: python/smoke run: PYTHON=python3-debug TOX=false VERSION=3.10 ./venv.sh @@ -45,6 +48,7 @@ - python3-tkinter # for selftest - python3-test # for selftest - tox # for venv tests + - virtualenv # for virtualenv tests - glibc-all-langpacks # for locale tests - marshalparser # for testing compatibility (magic numbers) with marshalparser - rpm # for debugging From d5c558ed2ad4ca87e5643c161c262f0170ea20e9 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 9 Nov 2021 18:20:35 +0100 Subject: [PATCH 021/112] Update patch 251 to include specific install scheme for virtualenv --- 00251-change-user-install-location.patch | 22 ++++++++++++++++------ python3.10.spec | 7 +++++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index 83c57ef..bf5a188 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -2,6 +2,9 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 15 Feb 2021 12:19:27 +0100 Subject: [PATCH] 00251: Change user install location +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Change the values of sysconfig's "posix_prefix" install scheme to /usr/local when RPM build or venv/virtualenv is not detected, @@ -22,11 +25,12 @@ Downstream only for now, waiting for https://bugs.python.org/issue43976 Co-authored-by: Petr Viktorin Co-authored-by: Miro Hrončok Co-authored-by: Michal Cyprian +Co-authored-by: Lumír Balhar --- Lib/site.py | 9 ++++++++- - Lib/sysconfig.py | 19 +++++++++++++++++++ + Lib/sysconfig.py | 25 +++++++++++++++++++++++++ Lib/test/test_sysconfig.py | 4 +++- - 3 files changed, 30 insertions(+), 2 deletions(-) + 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Lib/site.py b/Lib/site.py index 939893eb5e..d1316c3355 100644 @@ -50,16 +54,22 @@ index 939893eb5e..d1316c3355 100644 if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py -index 95b48f6429..226b55a556 100644 +index 95b48f6429..86072868d6 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py -@@ -58,6 +58,25 @@ +@@ -58,6 +58,31 @@ }, } +# backup the original posix_prefix as rpm_prefix +# RPM packages use it and we need to be able to read it even when changed +_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix'] ++# Virtualenv >= 20.10.0 favors the "venv" scheme over the defaults when creating virtual environments. ++# See: https://github.com/pypa/virtualenv/commit/8da79db86d8a5c74d03667a40e64ff832076445e ++# See: https://bugs.python.org/issue45413 ++# "venv" should be the same as the unpatched posix_prefix for us, ++# so new virtual environments aren't created with paths like venv/local/bin/python. ++_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_prefix'] + +if (not (hasattr(sys, 'real_prefix') or + sys.prefix != sys.base_prefix) and @@ -80,7 +90,7 @@ index 95b48f6429..226b55a556 100644 # NOTE: site.py has copy of this function. # Sync it when modify this function. diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py -index 9408657c91..db4cbc55ec 100644 +index 9408657c91..fd49b2bcce 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -263,7 +263,7 @@ def test_get_config_h_filename(self): @@ -88,7 +98,7 @@ index 9408657c91..db4cbc55ec 100644 def test_get_scheme_names(self): - wanted = ['nt', 'posix_home', 'posix_prefix'] -+ wanted = ['nt', 'posix_home', 'posix_prefix', 'rpm_prefix'] ++ wanted = ['nt', 'posix_home', 'posix_prefix', 'rpm_prefix', 'venv'] if HAS_USER_BASE: wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) diff --git a/python3.10.spec b/python3.10.spec index 84dec96..04e2688 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -267,7 +267,7 @@ Source11: idle3.appdata.xml # Was Patch0 in ivazquez' python3000 specfile Patch1: 00001-rpath.patch -# 00251 # 0952e38e5bf725ebbab48b13a35566e30635ddf8 +# 00251 # 531494a5ded29dad59f617304dab4eb8b7f80b0b # Change user install location # # Change the values of sysconfig's "posix_prefix" install scheme to /usr/local @@ -1596,6 +1596,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Nov 09 2021 Lumír Balhar - 3.10.0-3 +- Update patch 251 to include specific install scheme for virtualenv + * Tue Oct 05 2021 Miro Hrončok - 3.10.0-2 - Change the values of sysconfig's "posix_prefix" install scheme to /usr/local when RPM build or venv/virtualenv is not detected, From a707776bcf2b76226fcc49ba5f76aa138745d526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Fri, 12 Nov 2021 22:02:16 +0100 Subject: [PATCH 022/112] Rebuild(libnsl2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 04e2688..896096a 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python @@ -1596,6 +1596,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Nov 12 2021 Björn Esser - 3.10.0-4 +- Rebuild(libnsl2) + * Tue Nov 09 2021 Lumír Balhar - 3.10.0-3 - Update patch 251 to include specific install scheme for virtualenv From 4dc2200b8e81beeff7e672aa095f533e87b184c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Tue, 7 Dec 2021 08:54:16 +0100 Subject: [PATCH 023/112] Update to 3.10.1 --- 00001-rpath.patch | 2 +- 00251-change-user-install-location.patch | 2 +- 00328-pyc-timestamp-invalidation-mode.patch | 2 +- ...or-the-main-thread-gh-28549-gh-28589.patch | 103 ++++++++++++++++++ python3.10.spec | 22 +++- sources | 4 +- 6 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch diff --git a/00001-rpath.patch b/00001-rpath.patch index 170908e..778c077 100644 --- a/00001-rpath.patch +++ b/00001-rpath.patch @@ -9,7 +9,7 @@ Subject: [PATCH] 00001: Fixup distutils/unixccompiler.py to remove standard 1 file changed, 9 insertions(+) diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py -index f0792de74a..4d837936c6 100644 +index d00c48981e..0283a28c19 100644 --- a/Lib/distutils/unixccompiler.py +++ b/Lib/distutils/unixccompiler.py @@ -82,6 +82,15 @@ class UnixCCompiler(CCompiler): diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index bf5a188..ac6901d 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -54,7 +54,7 @@ index 939893eb5e..d1316c3355 100644 if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py -index 95b48f6429..86072868d6 100644 +index daf9f00006..40e4edf0ae 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -58,6 +58,31 @@ diff --git a/00328-pyc-timestamp-invalidation-mode.patch b/00328-pyc-timestamp-invalidation-mode.patch index 138868e..26f09f2 100644 --- a/00328-pyc-timestamp-invalidation-mode.patch +++ b/00328-pyc-timestamp-invalidation-mode.patch @@ -19,7 +19,7 @@ Ideally, we should talk to upstream and explain why we don't want this 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/py_compile.py b/Lib/py_compile.py -index 0f9b59025c..59dc3fe50b 100644 +index 388614e51b..db52725016 100644 --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -70,7 +70,8 @@ class PycInvalidationMode(enum.Enum): 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 new file mode 100644 index 0000000..5c814ef --- /dev/null +++ b/00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= +Date: Tue, 7 Dec 2021 14:41:59 +0100 +Subject: [PATCH] 00371: Revert "bpo-1596321: Fix threading._shutdown() for the + main thread (GH-28549) (GH-28589)" + +This reverts commit 38c67738c64304928c68d5c2bd78bbb01d979b94. It +introduced regression causing FreeIPA's tests to fail. + +For more info see: +https://bodhi.fedoraproject.org/updates/FEDORA-2021-e152ce5f31 +https://github.com/GrahamDumpleton/mod_wsgi/issues/730 +--- + Lib/test/test_threading.py | 33 --------------------------------- + Lib/threading.py | 25 ++++++++----------------- + 2 files changed, 8 insertions(+), 50 deletions(-) + +diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py +index c54806e594..c51de6f4b8 100644 +--- a/Lib/test/test_threading.py ++++ b/Lib/test/test_threading.py +@@ -928,39 +928,6 @@ def test_debug_deprecation(self): + b'is deprecated and will be removed in Python 3.12') + self.assertIn(msg, err) + +- def test_import_from_another_thread(self): +- # bpo-1596321: If the threading module is first import from a thread +- # different than the main thread, threading._shutdown() must handle +- # this case without logging an error at Python exit. +- code = textwrap.dedent(''' +- import _thread +- import sys +- +- event = _thread.allocate_lock() +- event.acquire() +- +- def import_threading(): +- import threading +- event.release() +- +- if 'threading' in sys.modules: +- raise Exception('threading is already imported') +- +- _thread.start_new_thread(import_threading, ()) +- +- # wait until the threading module is imported +- event.acquire() +- event.release() +- +- if 'threading' not in sys.modules: +- raise Exception('threading is not imported') +- +- # don't wait until the thread completes +- ''') +- rc, out, err = assert_python_ok("-c", code) +- self.assertEqual(out, b'') +- self.assertEqual(err, b'') +- + + class ThreadJoinOnShutdown(BaseTestCase): + +diff --git a/Lib/threading.py b/Lib/threading.py +index 2d89742913..928b3f715d 100644 +--- a/Lib/threading.py ++++ b/Lib/threading.py +@@ -1523,29 +1523,20 @@ def _shutdown(): + + global _SHUTTING_DOWN + _SHUTTING_DOWN = True ++ # Main thread ++ tlock = _main_thread._tstate_lock ++ # The main thread isn't finished yet, so its thread state lock can't have ++ # been released. ++ assert tlock is not None ++ assert tlock.locked() ++ tlock.release() ++ _main_thread._stop() + + # Call registered threading atexit functions before threads are joined. + # Order is reversed, similar to atexit. + for atexit_call in reversed(_threading_atexits): + atexit_call() + +- # Main thread +- if _main_thread.ident == get_ident(): +- tlock = _main_thread._tstate_lock +- # The main thread isn't finished yet, so its thread state lock can't +- # have been released. +- assert tlock is not None +- assert tlock.locked() +- tlock.release() +- _main_thread._stop() +- else: +- # bpo-1596321: _shutdown() must be called in the main thread. +- # If the threading module was not imported by the main thread, +- # _main_thread is the thread which imported the threading module. +- # In this case, ignore _main_thread, similar behavior than for threads +- # spawned by C libraries or using _thread.start_new_thread(). +- pass +- + # Join all non-deamon threads + while True: + with _shutdown_locks_lock: diff --git a/python3.10.spec b/python3.10.spec index 896096a..27d3e8d 100644 --- a/python3.10.spec +++ b/python3.10.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}.0 +%global general_version %{pybasever}.1 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 1%{?dist} License: Python @@ -68,8 +68,8 @@ License: Python # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 21.2.3 -%global setuptools_version 57.4.0 +%global pip_version 21.2.4 +%global setuptools_version 58.1.0 # Expensive optimizations (mainly, profile-guided optimizations) %bcond_without optimizations @@ -301,6 +301,17 @@ Patch251: 00251-change-user-install-location.patch # Ideally, we should talk to upstream and explain why we don't want this Patch328: 00328-pyc-timestamp-invalidation-mode.patch +# 00371 # c1754d9c2750f89cb702e1b63a99201f5f7cff00 +# Revert "bpo-1596321: Fix threading._shutdown() for the main thread (GH-28549) (GH-28589)" +# +# This reverts commit 38c67738c64304928c68d5c2bd78bbb01d979b94. It +# introduced regression causing FreeIPA's tests to fail. +# +# For more info see: +# https://bodhi.fedoraproject.org/updates/FEDORA-2021-e152ce5f31 +# https://github.com/GrahamDumpleton/mod_wsgi/issues/730 +Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1596,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Dec 07 2021 Tomáš Hrnčiar - 3.10.1-1 +- Update to 3.10.1 + * Fri Nov 12 2021 Björn Esser - 3.10.0-4 - Rebuild(libnsl2) diff --git a/sources b/sources index 29a970b..41d82f2 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.0.tar.xz) = 82b2729afc7d72a80882f199970667dce7d971a2e5ecfe6cf84f7b68612ab2caf6ed6d7a8cb81f24ea85cb0816464bb2e8b2e6884eda62fa40742edc674193bd -SHA512 (Python-3.10.0.tar.xz.asc) = 67236e02bc49da1423717cb54216b745f613ba2fc4b372a4aa15a36ab15fe69d9b9087070382957d480df7576d13056caedcd979fb56531799a1190b822f673d +SHA512 (Python-3.10.1.tar.xz) = 1c559e33f1252e51bafb941c380de16f142c0735858363c84cb8dbed6767843de3af126889c2826ffb94bd4777d7cdfc31040301c8c74de56af52b80b1aa9e76 +SHA512 (Python-3.10.1.tar.xz.asc) = 645d5f40e6e80a590923a48763f20dea7da3f3eea5825bb79e08618d81d1b8eee0ddee2b57503321a584280536e0671e4913e5ad450568fbbb44509c01d3907d From ac4f8985467a89da9c93fdc497b9e5a210886d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Sat, 8 Jan 2022 11:12:32 +0100 Subject: [PATCH 024/112] Rebuilt for https://fedoraproject.org/wiki/Changes/LIBFFI34 --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 27d3e8d..ae4704f 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -1607,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Sat Jan 08 2022 Miro Hrončok - 3.10.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Changes/LIBFFI34 + * Tue Dec 07 2021 Tomáš Hrnčiar - 3.10.1-1 - Update to 3.10.1 From 00a20f7f43d189a29a3c3fafa0cad7dab1e2d10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 10 Jan 2022 15:22:28 +0100 Subject: [PATCH 025/112] Backport fixes for two Python 3.10.1 regressions Fixes https://bugzilla.redhat.com/2030621 Fixes https://bugzilla.redhat.com/2034962 --- ...521-per-interpreter-interned-strings.patch | 302 ++++++++++++++++++ ...070-fix-asyncio-initialisation-guard.patch | 60 ++++ python3.10.spec | 35 +- 3 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch create mode 100644 00374-bpo-46070-fix-asyncio-initialisation-guard.patch diff --git a/00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch b/00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch new file mode 100644 index 0000000..fac1cf8 --- /dev/null +++ b/00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch @@ -0,0 +1,302 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Stinner +Date: Thu, 6 Jan 2022 16:12:28 +0100 +Subject: [PATCH] 00373: bpo-46006: Revert "bpo-40521: Per-interpreter interned + strings + +This reverts commit ea251806b8dffff11b30d2182af1e589caf88acf. + +Keep "assert(interned == NULL);" in _PyUnicode_Fini(), but only for +the main interpreter. + +Keep _PyUnicode_ClearInterned() changes avoiding the creation of a +temporary Python list object. + +Leave the PyInterpreterState structure unchanged to keep the ABI +backward compatibility with Python 3.10.0: rename the "interned" +member to "unused_interned". + +Fixes https://bugzilla.redhat.com/2030621 +--- + Include/internal/pycore_interp.h | 12 +--- + .../2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst | 5 ++ + Objects/typeobject.c | 22 +++++++ + Objects/unicodeobject.c | 63 ++++++++++++++----- + 4 files changed, 76 insertions(+), 26 deletions(-) + create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst + +diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h +index bfd082b588..4307b61ca3 100644 +--- a/Include/internal/pycore_interp.h ++++ b/Include/internal/pycore_interp.h +@@ -71,15 +71,9 @@ struct _Py_unicode_state { + PyObject *latin1[256]; + struct _Py_unicode_fs_codec fs_codec; + +- /* This dictionary holds all interned unicode strings. Note that references +- to strings in this dictionary are *not* counted in the string's ob_refcnt. +- When the interned string reaches a refcnt of 0 the string deallocation +- function will delete the reference from this dictionary. +- +- Another way to look at this is that to say that the actual reference +- count of a string is: s->ob_refcnt + (s->state ? 2 : 0) +- */ +- PyObject *interned; ++ // Unused member kept for ABI backward compatibility with Python 3.10.0: ++ // see bpo-46006. ++ PyObject *unused_interned; + + // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() + struct _Py_unicode_ids ids; +diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst +new file mode 100644 +index 0000000000..3acd2b0939 +--- /dev/null ++++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst +@@ -0,0 +1,5 @@ ++Fix a regression when a type method like ``__init__()`` is modified in a ++subinterpreter. Fix a regression in ``_PyUnicode_EqualToASCIIId()`` and type ++``update_slot()``. Revert the change which made the Unicode dictionary of ++interned strings compatible with subinterpreters: the internal interned ++dictionary is shared again by all interpreters. Patch by Victor Stinner. +diff --git a/Objects/typeobject.c b/Objects/typeobject.c +index 02046e5f2e..b23e36a420 100644 +--- a/Objects/typeobject.c ++++ b/Objects/typeobject.c +@@ -50,6 +50,11 @@ typedef struct PySlot_Offset { + } PySlot_Offset; + + ++/* bpo-40521: Interned strings are shared by all subinterpreters */ ++#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS ++# define INTERN_NAME_STRINGS ++#endif ++ + /* alphabetical order */ + _Py_IDENTIFIER(__abstractmethods__); + _Py_IDENTIFIER(__annotations__); +@@ -3988,6 +3993,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) + if (name == NULL) + return -1; + } ++#ifdef INTERN_NAME_STRINGS + if (!PyUnicode_CHECK_INTERNED(name)) { + PyUnicode_InternInPlace(&name); + if (!PyUnicode_CHECK_INTERNED(name)) { +@@ -3997,6 +4003,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) + return -1; + } + } ++#endif + } + else { + /* Will fail in _PyObject_GenericSetAttrWithDict. */ +@@ -8344,10 +8351,17 @@ _PyTypes_InitSlotDefs(void) + for (slotdef *p = slotdefs; p->name; p++) { + /* Slots must be ordered by their offset in the PyHeapTypeObject. */ + assert(!p[1].name || p->offset <= p[1].offset); ++#ifdef INTERN_NAME_STRINGS + p->name_strobj = PyUnicode_InternFromString(p->name); + if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) { + return _PyStatus_NO_MEMORY(); + } ++#else ++ p->name_strobj = PyUnicode_FromString(p->name); ++ if (!p->name_strobj) { ++ return _PyStatus_NO_MEMORY(); ++ } ++#endif + } + slotdefs_initialized = 1; + return _PyStatus_OK(); +@@ -8372,16 +8386,24 @@ update_slot(PyTypeObject *type, PyObject *name) + int offset; + + assert(PyUnicode_CheckExact(name)); ++#ifdef INTERN_NAME_STRINGS + assert(PyUnicode_CHECK_INTERNED(name)); ++#endif + + assert(slotdefs_initialized); + pp = ptrs; + for (p = slotdefs; p->name; p++) { + assert(PyUnicode_CheckExact(p->name_strobj)); + assert(PyUnicode_CheckExact(name)); ++#ifdef INTERN_NAME_STRINGS + if (p->name_strobj == name) { + *pp++ = p; + } ++#else ++ if (p->name_strobj == name || _PyUnicode_EQ(p->name_strobj, name)) { ++ *pp++ = p; ++ } ++#endif + } + *pp = NULL; + for (pp = ptrs; *pp; pp++) { +diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c +index c72871074b..077cf8d7f4 100644 +--- a/Objects/unicodeobject.c ++++ b/Objects/unicodeobject.c +@@ -211,6 +211,22 @@ extern "C" { + # define OVERALLOCATE_FACTOR 4 + #endif + ++/* bpo-40521: Interned strings are shared by all interpreters. */ ++#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS ++# define INTERNED_STRINGS ++#endif ++ ++/* This dictionary holds all interned unicode strings. Note that references ++ to strings in this dictionary are *not* counted in the string's ob_refcnt. ++ When the interned string reaches a refcnt of 0 the string deallocation ++ function will delete the reference from this dictionary. ++ ++ Another way to look at this is that to say that the actual reference ++ count of a string is: s->ob_refcnt + (s->state ? 2 : 0) ++*/ ++#ifdef INTERNED_STRINGS ++static PyObject *interned = NULL; ++#endif + + static struct _Py_unicode_state* + get_unicode_state(void) +@@ -1936,7 +1952,7 @@ unicode_dealloc(PyObject *unicode) + + case SSTATE_INTERNED_MORTAL: + { +- struct _Py_unicode_state *state = get_unicode_state(); ++#ifdef INTERNED_STRINGS + /* Revive the dead object temporarily. PyDict_DelItem() removes two + references (key and value) which were ignored by + PyUnicode_InternInPlace(). Use refcnt=3 rather than refcnt=2 +@@ -1944,12 +1960,13 @@ unicode_dealloc(PyObject *unicode) + PyDict_DelItem(). */ + assert(Py_REFCNT(unicode) == 0); + Py_SET_REFCNT(unicode, 3); +- if (PyDict_DelItem(state->interned, unicode) != 0) { ++ if (PyDict_DelItem(interned, unicode) != 0) { + _PyErr_WriteUnraisableMsg("deletion of interned string failed", + NULL); + } + assert(Py_REFCNT(unicode) == 1); + Py_SET_REFCNT(unicode, 0); ++#endif + break; + } + +@@ -11600,11 +11617,13 @@ _PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right) + if (PyUnicode_CHECK_INTERNED(left)) + return 0; + ++#ifdef INTERNED_STRINGS + assert(_PyUnicode_HASH(right_uni) != -1); + Py_hash_t hash = _PyUnicode_HASH(left); + if (hash != -1 && hash != _PyUnicode_HASH(right_uni)) { + return 0; + } ++#endif + + return unicode_compare_eq(left, right_uni); + } +@@ -15833,21 +15852,21 @@ PyUnicode_InternInPlace(PyObject **p) + return; + } + ++#ifdef INTERNED_STRINGS + if (PyUnicode_READY(s) == -1) { + PyErr_Clear(); + return; + } + +- struct _Py_unicode_state *state = get_unicode_state(); +- if (state->interned == NULL) { +- state->interned = PyDict_New(); +- if (state->interned == NULL) { ++ if (interned == NULL) { ++ interned = PyDict_New(); ++ if (interned == NULL) { + PyErr_Clear(); /* Don't leave an exception */ + return; + } + } + +- PyObject *t = PyDict_SetDefault(state->interned, s, s); ++ PyObject *t = PyDict_SetDefault(interned, s, s); + if (t == NULL) { + PyErr_Clear(); + return; +@@ -15864,9 +15883,13 @@ PyUnicode_InternInPlace(PyObject **p) + this. */ + Py_SET_REFCNT(s, Py_REFCNT(s) - 2); + _PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL; ++#else ++ // PyDict expects that interned strings have their hash ++ // (PyASCIIObject.hash) already computed. ++ (void)unicode_hash(s); ++#endif + } + +- + void + PyUnicode_InternImmortal(PyObject **p) + { +@@ -15900,11 +15923,15 @@ PyUnicode_InternFromString(const char *cp) + void + _PyUnicode_ClearInterned(PyInterpreterState *interp) + { +- struct _Py_unicode_state *state = &interp->unicode; +- if (state->interned == NULL) { ++ if (!_Py_IsMainInterpreter(interp)) { ++ // interned dict is shared by all interpreters + return; + } +- assert(PyDict_CheckExact(state->interned)); ++ ++ if (interned == NULL) { ++ return; ++ } ++ assert(PyDict_CheckExact(interned)); + + /* Interned unicode strings are not forcibly deallocated; rather, we give + them their stolen references back, and then clear and DECREF the +@@ -15912,13 +15939,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) + + #ifdef INTERNED_STATS + fprintf(stderr, "releasing %zd interned strings\n", +- PyDict_GET_SIZE(state->interned)); ++ PyDict_GET_SIZE(interned)); + + Py_ssize_t immortal_size = 0, mortal_size = 0; + #endif + Py_ssize_t pos = 0; + PyObject *s, *ignored_value; +- while (PyDict_Next(state->interned, &pos, &s, &ignored_value)) { ++ while (PyDict_Next(interned, &pos, &s, &ignored_value)) { + assert(PyUnicode_IS_READY(s)); + + switch (PyUnicode_CHECK_INTERNED(s)) { +@@ -15949,8 +15976,8 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) + mortal_size, immortal_size); + #endif + +- PyDict_Clear(state->interned); +- Py_CLEAR(state->interned); ++ PyDict_Clear(interned); ++ Py_CLEAR(interned); + } + + +@@ -16322,8 +16349,10 @@ _PyUnicode_Fini(PyInterpreterState *interp) + { + struct _Py_unicode_state *state = &interp->unicode; + +- // _PyUnicode_ClearInterned() must be called before +- assert(state->interned == NULL); ++ if (_Py_IsMainInterpreter(interp)) { ++ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini() ++ assert(interned == NULL); ++ } + + _PyUnicode_FiniEncodings(&state->fs_codec); + diff --git a/00374-bpo-46070-fix-asyncio-initialisation-guard.patch b/00374-bpo-46070-fix-asyncio-initialisation-guard.patch new file mode 100644 index 0000000..cc5b32f --- /dev/null +++ b/00374-bpo-46070-fix-asyncio-initialisation-guard.patch @@ -0,0 +1,60 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Fri, 7 Jan 2022 06:35:15 -0800 +Subject: [PATCH] 00374: bpo-46070: Fix asyncio initialisation guard + +If init flag is set, exit successfully immediately. +If not, only set the flag after successful initialization. +(cherry picked from commit b127e70a8a682fe869c22ce04c379bd85a00db67) + +Co-authored-by: Erlend Egeberg Aasland + +Fixes https://bugzilla.redhat.com/2034962 +--- + .../Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst | 2 ++ + Modules/_asynciomodule.c | 10 ++++------ + 2 files changed, 6 insertions(+), 6 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst + +diff --git a/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst b/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst +new file mode 100644 +index 0000000000..0fedc9dfb8 +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst +@@ -0,0 +1,2 @@ ++Fix possible segfault when importing the :mod:`asyncio` module from ++different sub-interpreters in parallel. Patch by Erlend E. Aasland. +diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c +index 56079b0277..befec9a834 100644 +--- a/Modules/_asynciomodule.c ++++ b/Modules/_asynciomodule.c +@@ -3309,17 +3309,14 @@ static int + module_init(void) + { + PyObject *module = NULL; ++ if (module_initialized) { ++ return 0; ++ } + + asyncio_mod = PyImport_ImportModule("asyncio"); + if (asyncio_mod == NULL) { + goto fail; + } +- if (module_initialized != 0) { +- return 0; +- } +- else { +- module_initialized = 1; +- } + + current_tasks = PyDict_New(); + if (current_tasks == NULL) { +@@ -3380,6 +3377,7 @@ module_init(void) + goto fail; + } + ++ module_initialized = 1; + Py_DECREF(module); + return 0; + diff --git a/python3.10.spec b/python3.10.spec index ae4704f..d1fdd89 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -312,6 +312,34 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00373 # 89f7a91bcd1c7227cb639667801e77de52f67b01 +# bpo-46006: Revert "bpo-40521: Per-interpreter interned strings +# +# This reverts commit ea251806b8dffff11b30d2182af1e589caf88acf. +# +# Keep "assert(interned == NULL);" in _PyUnicode_Fini(), but only for +# the main interpreter. +# +# Keep _PyUnicode_ClearInterned() changes avoiding the creation of a +# temporary Python list object. +# +# Leave the PyInterpreterState structure unchanged to keep the ABI +# backward compatibility with Python 3.10.0: rename the "interned" +# member to "unused_interned". +# +# Fixes https://bugzilla.redhat.com/2030621 +Patch373: 00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch + +# 00374 # 2e91fe5327e83ff8fb21d343b01babb611ae2027 +# bpo-46070: Fix asyncio initialisation guard +# +# If init flag is set, exit successfully immediately. +# If not, only set the flag after successful initialization. +# +# +# Fixes https://bugzilla.redhat.com/2034962 +Patch374: 00374-bpo-46070-fix-asyncio-initialisation-guard.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1607,6 +1635,11 @@ CheckPython optimized # ====================================================== %changelog +* Mon Jan 10 2022 Miro Hrončok - 3.10.1-3 +- Backport fixes for two Python 3.10.1 regressions +- Fixes: rhbz#2030621 +- Fixes: rhbz#2034962 + * Sat Jan 08 2022 Miro Hrončok - 3.10.1-2 - Rebuilt for https://fedoraproject.org/wiki/Changes/LIBFFI34 From bba9c24200aa1542f338e8d20f909653f03b2994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Mon, 17 Jan 2022 08:43:27 +0100 Subject: [PATCH 026/112] Update to 3.10.2 --- ...521-per-interpreter-interned-strings.patch | 302 ------------------ ...070-fix-asyncio-initialisation-guard.patch | 60 ---- python3.10.spec | 35 +- sources | 4 +- 4 files changed, 7 insertions(+), 394 deletions(-) delete mode 100644 00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch delete mode 100644 00374-bpo-46070-fix-asyncio-initialisation-guard.patch diff --git a/00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch b/00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch deleted file mode 100644 index fac1cf8..0000000 --- a/00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Stinner -Date: Thu, 6 Jan 2022 16:12:28 +0100 -Subject: [PATCH] 00373: bpo-46006: Revert "bpo-40521: Per-interpreter interned - strings - -This reverts commit ea251806b8dffff11b30d2182af1e589caf88acf. - -Keep "assert(interned == NULL);" in _PyUnicode_Fini(), but only for -the main interpreter. - -Keep _PyUnicode_ClearInterned() changes avoiding the creation of a -temporary Python list object. - -Leave the PyInterpreterState structure unchanged to keep the ABI -backward compatibility with Python 3.10.0: rename the "interned" -member to "unused_interned". - -Fixes https://bugzilla.redhat.com/2030621 ---- - Include/internal/pycore_interp.h | 12 +--- - .../2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst | 5 ++ - Objects/typeobject.c | 22 +++++++ - Objects/unicodeobject.c | 63 ++++++++++++++----- - 4 files changed, 76 insertions(+), 26 deletions(-) - create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst - -diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h -index bfd082b588..4307b61ca3 100644 ---- a/Include/internal/pycore_interp.h -+++ b/Include/internal/pycore_interp.h -@@ -71,15 +71,9 @@ struct _Py_unicode_state { - PyObject *latin1[256]; - struct _Py_unicode_fs_codec fs_codec; - -- /* This dictionary holds all interned unicode strings. Note that references -- to strings in this dictionary are *not* counted in the string's ob_refcnt. -- When the interned string reaches a refcnt of 0 the string deallocation -- function will delete the reference from this dictionary. -- -- Another way to look at this is that to say that the actual reference -- count of a string is: s->ob_refcnt + (s->state ? 2 : 0) -- */ -- PyObject *interned; -+ // Unused member kept for ABI backward compatibility with Python 3.10.0: -+ // see bpo-46006. -+ PyObject *unused_interned; - - // Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId() - struct _Py_unicode_ids ids; -diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst -new file mode 100644 -index 0000000000..3acd2b0939 ---- /dev/null -+++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-05-17-13-47.bpo-46006.hdH5Vn.rst -@@ -0,0 +1,5 @@ -+Fix a regression when a type method like ``__init__()`` is modified in a -+subinterpreter. Fix a regression in ``_PyUnicode_EqualToASCIIId()`` and type -+``update_slot()``. Revert the change which made the Unicode dictionary of -+interned strings compatible with subinterpreters: the internal interned -+dictionary is shared again by all interpreters. Patch by Victor Stinner. -diff --git a/Objects/typeobject.c b/Objects/typeobject.c -index 02046e5f2e..b23e36a420 100644 ---- a/Objects/typeobject.c -+++ b/Objects/typeobject.c -@@ -50,6 +50,11 @@ typedef struct PySlot_Offset { - } PySlot_Offset; - - -+/* bpo-40521: Interned strings are shared by all subinterpreters */ -+#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS -+# define INTERN_NAME_STRINGS -+#endif -+ - /* alphabetical order */ - _Py_IDENTIFIER(__abstractmethods__); - _Py_IDENTIFIER(__annotations__); -@@ -3988,6 +3993,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) - if (name == NULL) - return -1; - } -+#ifdef INTERN_NAME_STRINGS - if (!PyUnicode_CHECK_INTERNED(name)) { - PyUnicode_InternInPlace(&name); - if (!PyUnicode_CHECK_INTERNED(name)) { -@@ -3997,6 +4003,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) - return -1; - } - } -+#endif - } - else { - /* Will fail in _PyObject_GenericSetAttrWithDict. */ -@@ -8344,10 +8351,17 @@ _PyTypes_InitSlotDefs(void) - for (slotdef *p = slotdefs; p->name; p++) { - /* Slots must be ordered by their offset in the PyHeapTypeObject. */ - assert(!p[1].name || p->offset <= p[1].offset); -+#ifdef INTERN_NAME_STRINGS - p->name_strobj = PyUnicode_InternFromString(p->name); - if (!p->name_strobj || !PyUnicode_CHECK_INTERNED(p->name_strobj)) { - return _PyStatus_NO_MEMORY(); - } -+#else -+ p->name_strobj = PyUnicode_FromString(p->name); -+ if (!p->name_strobj) { -+ return _PyStatus_NO_MEMORY(); -+ } -+#endif - } - slotdefs_initialized = 1; - return _PyStatus_OK(); -@@ -8372,16 +8386,24 @@ update_slot(PyTypeObject *type, PyObject *name) - int offset; - - assert(PyUnicode_CheckExact(name)); -+#ifdef INTERN_NAME_STRINGS - assert(PyUnicode_CHECK_INTERNED(name)); -+#endif - - assert(slotdefs_initialized); - pp = ptrs; - for (p = slotdefs; p->name; p++) { - assert(PyUnicode_CheckExact(p->name_strobj)); - assert(PyUnicode_CheckExact(name)); -+#ifdef INTERN_NAME_STRINGS - if (p->name_strobj == name) { - *pp++ = p; - } -+#else -+ if (p->name_strobj == name || _PyUnicode_EQ(p->name_strobj, name)) { -+ *pp++ = p; -+ } -+#endif - } - *pp = NULL; - for (pp = ptrs; *pp; pp++) { -diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c -index c72871074b..077cf8d7f4 100644 ---- a/Objects/unicodeobject.c -+++ b/Objects/unicodeobject.c -@@ -211,6 +211,22 @@ extern "C" { - # define OVERALLOCATE_FACTOR 4 - #endif - -+/* bpo-40521: Interned strings are shared by all interpreters. */ -+#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS -+# define INTERNED_STRINGS -+#endif -+ -+/* This dictionary holds all interned unicode strings. Note that references -+ to strings in this dictionary are *not* counted in the string's ob_refcnt. -+ When the interned string reaches a refcnt of 0 the string deallocation -+ function will delete the reference from this dictionary. -+ -+ Another way to look at this is that to say that the actual reference -+ count of a string is: s->ob_refcnt + (s->state ? 2 : 0) -+*/ -+#ifdef INTERNED_STRINGS -+static PyObject *interned = NULL; -+#endif - - static struct _Py_unicode_state* - get_unicode_state(void) -@@ -1936,7 +1952,7 @@ unicode_dealloc(PyObject *unicode) - - case SSTATE_INTERNED_MORTAL: - { -- struct _Py_unicode_state *state = get_unicode_state(); -+#ifdef INTERNED_STRINGS - /* Revive the dead object temporarily. PyDict_DelItem() removes two - references (key and value) which were ignored by - PyUnicode_InternInPlace(). Use refcnt=3 rather than refcnt=2 -@@ -1944,12 +1960,13 @@ unicode_dealloc(PyObject *unicode) - PyDict_DelItem(). */ - assert(Py_REFCNT(unicode) == 0); - Py_SET_REFCNT(unicode, 3); -- if (PyDict_DelItem(state->interned, unicode) != 0) { -+ if (PyDict_DelItem(interned, unicode) != 0) { - _PyErr_WriteUnraisableMsg("deletion of interned string failed", - NULL); - } - assert(Py_REFCNT(unicode) == 1); - Py_SET_REFCNT(unicode, 0); -+#endif - break; - } - -@@ -11600,11 +11617,13 @@ _PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right) - if (PyUnicode_CHECK_INTERNED(left)) - return 0; - -+#ifdef INTERNED_STRINGS - assert(_PyUnicode_HASH(right_uni) != -1); - Py_hash_t hash = _PyUnicode_HASH(left); - if (hash != -1 && hash != _PyUnicode_HASH(right_uni)) { - return 0; - } -+#endif - - return unicode_compare_eq(left, right_uni); - } -@@ -15833,21 +15852,21 @@ PyUnicode_InternInPlace(PyObject **p) - return; - } - -+#ifdef INTERNED_STRINGS - if (PyUnicode_READY(s) == -1) { - PyErr_Clear(); - return; - } - -- struct _Py_unicode_state *state = get_unicode_state(); -- if (state->interned == NULL) { -- state->interned = PyDict_New(); -- if (state->interned == NULL) { -+ if (interned == NULL) { -+ interned = PyDict_New(); -+ if (interned == NULL) { - PyErr_Clear(); /* Don't leave an exception */ - return; - } - } - -- PyObject *t = PyDict_SetDefault(state->interned, s, s); -+ PyObject *t = PyDict_SetDefault(interned, s, s); - if (t == NULL) { - PyErr_Clear(); - return; -@@ -15864,9 +15883,13 @@ PyUnicode_InternInPlace(PyObject **p) - this. */ - Py_SET_REFCNT(s, Py_REFCNT(s) - 2); - _PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL; -+#else -+ // PyDict expects that interned strings have their hash -+ // (PyASCIIObject.hash) already computed. -+ (void)unicode_hash(s); -+#endif - } - -- - void - PyUnicode_InternImmortal(PyObject **p) - { -@@ -15900,11 +15923,15 @@ PyUnicode_InternFromString(const char *cp) - void - _PyUnicode_ClearInterned(PyInterpreterState *interp) - { -- struct _Py_unicode_state *state = &interp->unicode; -- if (state->interned == NULL) { -+ if (!_Py_IsMainInterpreter(interp)) { -+ // interned dict is shared by all interpreters - return; - } -- assert(PyDict_CheckExact(state->interned)); -+ -+ if (interned == NULL) { -+ return; -+ } -+ assert(PyDict_CheckExact(interned)); - - /* Interned unicode strings are not forcibly deallocated; rather, we give - them their stolen references back, and then clear and DECREF the -@@ -15912,13 +15939,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) - - #ifdef INTERNED_STATS - fprintf(stderr, "releasing %zd interned strings\n", -- PyDict_GET_SIZE(state->interned)); -+ PyDict_GET_SIZE(interned)); - - Py_ssize_t immortal_size = 0, mortal_size = 0; - #endif - Py_ssize_t pos = 0; - PyObject *s, *ignored_value; -- while (PyDict_Next(state->interned, &pos, &s, &ignored_value)) { -+ while (PyDict_Next(interned, &pos, &s, &ignored_value)) { - assert(PyUnicode_IS_READY(s)); - - switch (PyUnicode_CHECK_INTERNED(s)) { -@@ -15949,8 +15976,8 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) - mortal_size, immortal_size); - #endif - -- PyDict_Clear(state->interned); -- Py_CLEAR(state->interned); -+ PyDict_Clear(interned); -+ Py_CLEAR(interned); - } - - -@@ -16322,8 +16349,10 @@ _PyUnicode_Fini(PyInterpreterState *interp) - { - struct _Py_unicode_state *state = &interp->unicode; - -- // _PyUnicode_ClearInterned() must be called before -- assert(state->interned == NULL); -+ if (_Py_IsMainInterpreter(interp)) { -+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini() -+ assert(interned == NULL); -+ } - - _PyUnicode_FiniEncodings(&state->fs_codec); - diff --git a/00374-bpo-46070-fix-asyncio-initialisation-guard.patch b/00374-bpo-46070-fix-asyncio-initialisation-guard.patch deleted file mode 100644 index cc5b32f..0000000 --- a/00374-bpo-46070-fix-asyncio-initialisation-guard.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Miss Islington (bot)" - <31488909+miss-islington@users.noreply.github.com> -Date: Fri, 7 Jan 2022 06:35:15 -0800 -Subject: [PATCH] 00374: bpo-46070: Fix asyncio initialisation guard - -If init flag is set, exit successfully immediately. -If not, only set the flag after successful initialization. -(cherry picked from commit b127e70a8a682fe869c22ce04c379bd85a00db67) - -Co-authored-by: Erlend Egeberg Aasland - -Fixes https://bugzilla.redhat.com/2034962 ---- - .../Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst | 2 ++ - Modules/_asynciomodule.c | 10 ++++------ - 2 files changed, 6 insertions(+), 6 deletions(-) - create mode 100644 Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst - -diff --git a/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst b/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst -new file mode 100644 -index 0000000000..0fedc9dfb8 ---- /dev/null -+++ b/Misc/NEWS.d/next/Library/2022-01-07-13-51-22.bpo-46070.-axLUW.rst -@@ -0,0 +1,2 @@ -+Fix possible segfault when importing the :mod:`asyncio` module from -+different sub-interpreters in parallel. Patch by Erlend E. Aasland. -diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c -index 56079b0277..befec9a834 100644 ---- a/Modules/_asynciomodule.c -+++ b/Modules/_asynciomodule.c -@@ -3309,17 +3309,14 @@ static int - module_init(void) - { - PyObject *module = NULL; -+ if (module_initialized) { -+ return 0; -+ } - - asyncio_mod = PyImport_ImportModule("asyncio"); - if (asyncio_mod == NULL) { - goto fail; - } -- if (module_initialized != 0) { -- return 0; -- } -- else { -- module_initialized = 1; -- } - - current_tasks = PyDict_New(); - if (current_tasks == NULL) { -@@ -3380,6 +3377,7 @@ module_init(void) - goto fail; - } - -+ module_initialized = 1; - Py_DECREF(module); - return 0; - diff --git a/python3.10.spec b/python3.10.spec index d1fdd89..48cb765 100644 --- a/python3.10.spec +++ b/python3.10.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}.1 +%global general_version %{pybasever}.2 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python @@ -312,34 +312,6 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00373 # 89f7a91bcd1c7227cb639667801e77de52f67b01 -# bpo-46006: Revert "bpo-40521: Per-interpreter interned strings -# -# This reverts commit ea251806b8dffff11b30d2182af1e589caf88acf. -# -# Keep "assert(interned == NULL);" in _PyUnicode_Fini(), but only for -# the main interpreter. -# -# Keep _PyUnicode_ClearInterned() changes avoiding the creation of a -# temporary Python list object. -# -# Leave the PyInterpreterState structure unchanged to keep the ABI -# backward compatibility with Python 3.10.0: rename the "interned" -# member to "unused_interned". -# -# Fixes https://bugzilla.redhat.com/2030621 -Patch373: 00373-bpo-46006-revert-bpo-40521-per-interpreter-interned-strings.patch - -# 00374 # 2e91fe5327e83ff8fb21d343b01babb611ae2027 -# bpo-46070: Fix asyncio initialisation guard -# -# If init flag is set, exit successfully immediately. -# If not, only set the flag after successful initialization. -# -# -# Fixes https://bugzilla.redhat.com/2034962 -Patch374: 00374-bpo-46070-fix-asyncio-initialisation-guard.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1635,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Jan 17 2022 Tomáš Hrnčiar - 3.10.2-1 +- Update to 3.10.2 + * Mon Jan 10 2022 Miro Hrončok - 3.10.1-3 - Backport fixes for two Python 3.10.1 regressions - Fixes: rhbz#2030621 diff --git a/sources b/sources index 41d82f2..93254c3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.1.tar.xz) = 1c559e33f1252e51bafb941c380de16f142c0735858363c84cb8dbed6767843de3af126889c2826ffb94bd4777d7cdfc31040301c8c74de56af52b80b1aa9e76 -SHA512 (Python-3.10.1.tar.xz.asc) = 645d5f40e6e80a590923a48763f20dea7da3f3eea5825bb79e08618d81d1b8eee0ddee2b57503321a584280536e0671e4913e5ad450568fbbb44509c01d3907d +SHA512 (Python-3.10.2.tar.xz) = 215a7159face84788fe547c1e2689b8d0ae510275157cf01636bef2902d0ff465f844eb0328c9f39fd1cd03a1d1736d4cf258992f2788e492a801a372032c08b +SHA512 (Python-3.10.2.tar.xz.asc) = 086aeaa999d3005cc1f9057d90230c7a9e65d80f436febf16b0e8ba6f49645870ef21170ca1af50c8e2f51e6f46338cfad73a2d91320ad4a3315a2ae87eb70b4 From 7dd344e69a8587ad150d5080f8215c53dbf89c4a Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 21 Jan 2022 16:48:45 +0000 Subject: [PATCH 027/112] - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 48cb765..cc2c635 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -1607,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jan 21 2022 Fedora Release Engineering - 3.10.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + * Mon Jan 17 2022 Tomáš Hrnčiar - 3.10.2-1 - Update to 3.10.2 From 15f7528ae8f79811abd6057175be9f65582161a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Tue, 1 Feb 2022 14:30:18 +0100 Subject: [PATCH 028/112] Backport AC_C_CHAR_UNSIGNED/__CHAR_UNSIGNED__ removal --- ...ac_c_char_unsigned-__char_unsigned__.patch | 113 ++++++++++++++++++ python3.10.spec | 10 +- 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 00376-remove-ac_c_char_unsigned-__char_unsigned__.patch diff --git a/00376-remove-ac_c_char_unsigned-__char_unsigned__.patch b/00376-remove-ac_c_char_unsigned-__char_unsigned__.patch new file mode 100644 index 0000000..cd2acd2 --- /dev/null +++ b/00376-remove-ac_c_char_unsigned-__char_unsigned__.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Wed, 26 Jan 2022 13:20:31 +0200 +Subject: [PATCH] 00376: Remove AC_C_CHAR_UNSIGNED / __CHAR_UNSIGNED__ + +Co-authored-by: Christian Heimes +--- + .../2022-01-25-12-32-37.bpo-46513.mPm9B4.rst | 2 ++ + Modules/audioop.c | 7 ---- + configure | 33 ------------------- + configure.ac | 1 - + pyconfig.h.in | 5 --- + 5 files changed, 2 insertions(+), 46 deletions(-) + create mode 100644 Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst + +diff --git a/Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst b/Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst +new file mode 100644 +index 0000000000..b8986ae31a +--- /dev/null ++++ b/Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst +@@ -0,0 +1,2 @@ ++:program:`configure` no longer uses ``AC_C_CHAR_UNSIGNED`` macro and ++``pyconfig.h`` no longer defines reserved symbol ``__CHAR_UNSIGNED__``. +diff --git a/Modules/audioop.c b/Modules/audioop.c +index 3aeb6f04f1..2a5d805c05 100644 +--- a/Modules/audioop.c ++++ b/Modules/audioop.c +@@ -5,13 +5,6 @@ + + #include "Python.h" + +-#if defined(__CHAR_UNSIGNED__) +-#if defined(signed) +-/* This module currently does not work on systems where only unsigned +- characters are available. Take it out of Setup. Sorry. */ +-#endif +-#endif +- + static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF}; + /* -1 trick is needed on Windows to support -0x80000000 without a warning */ + static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1}; +diff --git a/configure b/configure +index a7d2975f1f..e68e00b0b3 100755 +--- a/configure ++++ b/configure +@@ -14183,39 +14183,6 @@ fi + + # checks for compiler characteristics + +-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 +-$as_echo_n "checking whether char is unsigned... " >&6; } +-if ${ac_cv_c_char_unsigned+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- cat confdefs.h - <<_ACEOF >conftest.$ac_ext +-/* end confdefs.h. */ +-$ac_includes_default +-int +-main () +-{ +-static int test_array [1 - 2 * !(((char) -1) < 0)]; +-test_array [0] = 0; +-return test_array [0]; +- +- ; +- return 0; +-} +-_ACEOF +-if ac_fn_c_try_compile "$LINENO"; then : +- ac_cv_c_char_unsigned=no +-else +- ac_cv_c_char_unsigned=yes +-fi +-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5 +-$as_echo "$ac_cv_c_char_unsigned" >&6; } +-if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then +- $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h +- +-fi +- + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 + $as_echo_n "checking for an ANSI C-conforming const... " >&6; } + if ${ac_cv_c_const+:} false; then : +diff --git a/configure.ac b/configure.ac +index 5aa91cbad3..0efeb8f585 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -4322,7 +4322,6 @@ fi + + # checks for compiler characteristics + +-AC_C_CHAR_UNSIGNED + AC_C_CONST + + works=no +diff --git a/pyconfig.h.in b/pyconfig.h.in +index b97b8f8bf8..8a4aeda646 100644 +--- a/pyconfig.h.in ++++ b/pyconfig.h.in +@@ -1656,11 +1656,6 @@ + /* Define on FreeBSD to activate all library features */ + #undef __BSD_VISIBLE + +-/* Define to 1 if type `char' is unsigned and you are not using gcc. */ +-#ifndef __CHAR_UNSIGNED__ +-# undef __CHAR_UNSIGNED__ +-#endif +- + /* Define to 'long' if doesn't define. */ + #undef clock_t + diff --git a/python3.10.spec b/python3.10.spec index cc2c635..636c32a 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -312,6 +312,10 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00376 # 9fecd19d88858a4a5ff753c9c91e857c897ff47a +# Remove AC_C_CHAR_UNSIGNED / __CHAR_UNSIGNED__ +Patch376: 00376-remove-ac_c_char_unsigned-__char_unsigned__.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1607,6 +1611,10 @@ CheckPython optimized # ====================================================== %changelog +* Tue Feb 01 2022 Tomáš Hrnčiar - 3.10.2-3 +- Backport AC_C_CHAR_UNSIGNED/__CHAR_UNSIGNED__ removal +- Fixes: rhbz#2043555 + * Fri Jan 21 2022 Fedora Release Engineering - 3.10.2-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild From 1e4699e5bc9390f0e1259bf1390140f9f0d1c4ea Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Wed, 29 Sep 2021 12:57:51 +0200 Subject: [PATCH 029/112] Use new macros %python_wheel_dir and %python_wheel_pkg_prefix ..for build/requiring wheel packages and for the file location. This does not actually change the name or the contents of the subpackage. --- python3.10.spec | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 636c32a..3441cff 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -226,8 +226,8 @@ BuildRequires: /usr/bin/dtrace BuildRequires: /usr/sbin/ifconfig %if %{with rpmwheels} -BuildRequires: python-setuptools-wheel -BuildRequires: python-pip-wheel +BuildRequires: %{python_wheel_pkg_prefix}-setuptools-wheel +BuildRequires: %{python_wheel_pkg_prefix}-pip-wheel %endif %if %{without bootstrap} @@ -440,8 +440,8 @@ This package contains /usr/bin/python - the "python" command that runs Python 3. Summary: Python runtime libraries %if %{with rpmwheels} -Requires: python-setuptools-wheel -Requires: python-pip-wheel +Requires: %{python_wheel_pkg_prefix}-setuptools-wheel +Requires: %{python_wheel_pkg_prefix}-pip-wheel %else Provides: bundled(python3dist(pip)) = %{pip_version} Provides: bundled(python3dist(setuptools)) = %{setuptools_version} @@ -605,8 +605,8 @@ Provides: python%{pyshortver} = %{version}-%{release} Obsoletes: python%{pyshortver} < %{version}-%{release} %if %{with rpmwheels} -Requires: python-setuptools-wheel -Requires: python-pip-wheel +Requires: %{python_wheel_pkg_prefix}-setuptools-wheel +Requires: %{python_wheel_pkg_prefix}-pip-wheel %else Provides: bundled(python3dist(pip)) = %{pip_version} Provides: bundled(python3dist(setuptools)) = %{setuptools_version} @@ -739,7 +739,7 @@ BuildPython() { --with-ssl-default-suites=openssl \ --without-static-libpython \ %if %{with rpmwheels} - --with-wheel-pkg-dir=%{_datadir}/python-wheels \ + --with-wheel-pkg-dir=%{python_wheel_dir} \ %endif %if %{with valgrind} --with-valgrind \ From 3d2cdb23806e5b6812808eaba26bb167075038d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Fri, 18 Mar 2022 08:54:06 +0100 Subject: [PATCH 030/112] Update to 3.10.3 --- ...ac_c_char_unsigned-__char_unsigned__.patch | 113 ------------------ python3.10.spec | 13 +- sources | 4 +- 3 files changed, 8 insertions(+), 122 deletions(-) delete mode 100644 00376-remove-ac_c_char_unsigned-__char_unsigned__.patch diff --git a/00376-remove-ac_c_char_unsigned-__char_unsigned__.patch b/00376-remove-ac_c_char_unsigned-__char_unsigned__.patch deleted file mode 100644 index cd2acd2..0000000 --- a/00376-remove-ac_c_char_unsigned-__char_unsigned__.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Wed, 26 Jan 2022 13:20:31 +0200 -Subject: [PATCH] 00376: Remove AC_C_CHAR_UNSIGNED / __CHAR_UNSIGNED__ - -Co-authored-by: Christian Heimes ---- - .../2022-01-25-12-32-37.bpo-46513.mPm9B4.rst | 2 ++ - Modules/audioop.c | 7 ---- - configure | 33 ------------------- - configure.ac | 1 - - pyconfig.h.in | 5 --- - 5 files changed, 2 insertions(+), 46 deletions(-) - create mode 100644 Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst - -diff --git a/Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst b/Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst -new file mode 100644 -index 0000000000..b8986ae31a ---- /dev/null -+++ b/Misc/NEWS.d/next/Build/2022-01-25-12-32-37.bpo-46513.mPm9B4.rst -@@ -0,0 +1,2 @@ -+:program:`configure` no longer uses ``AC_C_CHAR_UNSIGNED`` macro and -+``pyconfig.h`` no longer defines reserved symbol ``__CHAR_UNSIGNED__``. -diff --git a/Modules/audioop.c b/Modules/audioop.c -index 3aeb6f04f1..2a5d805c05 100644 ---- a/Modules/audioop.c -+++ b/Modules/audioop.c -@@ -5,13 +5,6 @@ - - #include "Python.h" - --#if defined(__CHAR_UNSIGNED__) --#if defined(signed) --/* This module currently does not work on systems where only unsigned -- characters are available. Take it out of Setup. Sorry. */ --#endif --#endif -- - static const int maxvals[] = {0, 0x7F, 0x7FFF, 0x7FFFFF, 0x7FFFFFFF}; - /* -1 trick is needed on Windows to support -0x80000000 without a warning */ - static const int minvals[] = {0, -0x80, -0x8000, -0x800000, -0x7FFFFFFF-1}; -diff --git a/configure b/configure -index a7d2975f1f..e68e00b0b3 100755 ---- a/configure -+++ b/configure -@@ -14183,39 +14183,6 @@ fi - - # checks for compiler characteristics - --{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 --$as_echo_n "checking whether char is unsigned... " >&6; } --if ${ac_cv_c_char_unsigned+:} false; then : -- $as_echo_n "(cached) " >&6 --else -- cat confdefs.h - <<_ACEOF >conftest.$ac_ext --/* end confdefs.h. */ --$ac_includes_default --int --main () --{ --static int test_array [1 - 2 * !(((char) -1) < 0)]; --test_array [0] = 0; --return test_array [0]; -- -- ; -- return 0; --} --_ACEOF --if ac_fn_c_try_compile "$LINENO"; then : -- ac_cv_c_char_unsigned=no --else -- ac_cv_c_char_unsigned=yes --fi --rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext --fi --{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_char_unsigned" >&5 --$as_echo "$ac_cv_c_char_unsigned" >&6; } --if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then -- $as_echo "#define __CHAR_UNSIGNED__ 1" >>confdefs.h -- --fi -- - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 - $as_echo_n "checking for an ANSI C-conforming const... " >&6; } - if ${ac_cv_c_const+:} false; then : -diff --git a/configure.ac b/configure.ac -index 5aa91cbad3..0efeb8f585 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -4322,7 +4322,6 @@ fi - - # checks for compiler characteristics - --AC_C_CHAR_UNSIGNED - AC_C_CONST - - works=no -diff --git a/pyconfig.h.in b/pyconfig.h.in -index b97b8f8bf8..8a4aeda646 100644 ---- a/pyconfig.h.in -+++ b/pyconfig.h.in -@@ -1656,11 +1656,6 @@ - /* Define on FreeBSD to activate all library features */ - #undef __BSD_VISIBLE - --/* Define to 1 if type `char' is unsigned and you are not using gcc. */ --#ifndef __CHAR_UNSIGNED__ --# undef __CHAR_UNSIGNED__ --#endif -- - /* Define to 'long' if doesn't define. */ - #undef clock_t - diff --git a/python3.10.spec b/python3.10.spec index 3441cff..20f547b 100644 --- a/python3.10.spec +++ b/python3.10.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}.2 +%global general_version %{pybasever}.3 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python @@ -68,7 +68,7 @@ License: Python # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 21.2.4 +%global pip_version 22.0.4 %global setuptools_version 58.1.0 # Expensive optimizations (mainly, profile-guided optimizations) @@ -312,10 +312,6 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00376 # 9fecd19d88858a4a5ff753c9c91e857c897ff47a -# Remove AC_C_CHAR_UNSIGNED / __CHAR_UNSIGNED__ -Patch376: 00376-remove-ac_c_char_unsigned-__char_unsigned__.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1611,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Mar 18 2022 Tomáš Hrnčiar - 3.10.3-1 +- Update to 3.10.3 + * Tue Feb 01 2022 Tomáš Hrnčiar - 3.10.2-3 - Backport AC_C_CHAR_UNSIGNED/__CHAR_UNSIGNED__ removal - Fixes: rhbz#2043555 diff --git a/sources b/sources index 93254c3..b36c6bc 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.2.tar.xz) = 215a7159face84788fe547c1e2689b8d0ae510275157cf01636bef2902d0ff465f844eb0328c9f39fd1cd03a1d1736d4cf258992f2788e492a801a372032c08b -SHA512 (Python-3.10.2.tar.xz.asc) = 086aeaa999d3005cc1f9057d90230c7a9e65d80f436febf16b0e8ba6f49645870ef21170ca1af50c8e2f51e6f46338cfad73a2d91320ad4a3315a2ae87eb70b4 +SHA512 (Python-3.10.3.tar.xz) = 5020407798ebaae6002b8de29475c1064a32f1527a0e4ec6fe7fcf076b4ea3ef0ab4b4a7864a6081cc8dd01dd545123198b11cc8dd1259c670394b7d81f35a86 +SHA512 (Python-3.10.3.tar.xz.asc) = ddbe55225fcdd5d36f6be4bb802ea8fb9c5e8cf1b573b76501cc0999bcbfb2355f5bf7bbe10bf7cb209e54f37ed0789b4b936920b208b2afc18597bab33f2f51 From fdfd6c1d945a381cbc85aa6d60b2369ac3ce7f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Fri, 25 Mar 2022 08:04:17 +0100 Subject: [PATCH 031/112] Update to 3.10.4 --- python3.10.spec | 5 ++++- sources | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 20f547b..a5e629a 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -13,7 +13,7 @@ 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}.3 +%global general_version %{pybasever}.4 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} @@ -1607,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Mar 25 2022 Tomáš Hrnčiar - 3.10.4-1 +- Update to 3.10.4 + * Fri Mar 18 2022 Tomáš Hrnčiar - 3.10.3-1 - Update to 3.10.3 diff --git a/sources b/sources index b36c6bc..46b98a4 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.3.tar.xz) = 5020407798ebaae6002b8de29475c1064a32f1527a0e4ec6fe7fcf076b4ea3ef0ab4b4a7864a6081cc8dd01dd545123198b11cc8dd1259c670394b7d81f35a86 -SHA512 (Python-3.10.3.tar.xz.asc) = ddbe55225fcdd5d36f6be4bb802ea8fb9c5e8cf1b573b76501cc0999bcbfb2355f5bf7bbe10bf7cb209e54f37ed0789b4b936920b208b2afc18597bab33f2f51 +SHA512 (Python-3.10.4.tar.xz) = 6c9aeecddc55c7896b2e8527fca131c7b2b6127d56ce1a001ccedfebf590334e0c0bb7c517ed3cf1da3c1910e002552b56aa7e03eeb672f42ff0bd8150799113 +SHA512 (Python-3.10.4.tar.xz.asc) = 699e37bf09067083af159e3734b38c952bdc75432c8abfb7a7b8cce7ca975038da37490abeb5c13befd2dacb84a5341ad30de5d0a63d35af5c512215744f4d6d From 8055248c0ef9d51c5f686119eb4fc1149f81ab12 Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:22:51 +0000 Subject: [PATCH 032/112] Build Python 3.11 with subpackages (by disabling the flatpackage bcond) No change in not providing `python(abi)` for alternative Python versions Resolves: rhbz#2063227 --- python3.10.spec | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index a5e629a..a58b005 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -40,13 +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): don't use the flatpackage structure for Python 3.11 and +# higher, remove the bcond from the spec in the future # Not supported: Combination of flatpackage enabled and main_python enabled -%if %{with main_python} %bcond_with flatpackage -%else -%bcond_without flatpackage -%endif # When bootstrapping python3, we need to build setuptools. # but setuptools BR python3-devel and that brings in python3-rpm-generators; @@ -330,6 +327,13 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # Descriptions, and metadata for subpackages # ========================================== +%if %{without main_python} +# We'll not provide this, on purpose +# No package in Fedora shall ever depend on a alternative Python via this +%global __requires_exclude ^python\\(abi\\) = 3\\..+ +%global __provides_exclude ^python\\(abi\\) = 3\\..+ +%endif # without main_python + # this if branch is ~300 lines long and contains subpackages' definitions %if %{without flatpackage} %if %{with main_python} @@ -374,9 +378,11 @@ Recommends: %{_bindir}/python Provides: python%{pyshortver} = %{version}-%{release} Obsoletes: python%{pyshortver} < %{version}-%{release} +%if %{with main_python} # Packages with Python modules in standard locations automatically # depend on python(abi). Provide that here. Provides: python(abi) = %{pybasever} +%endif # with main_python Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} @@ -489,7 +495,10 @@ Requires: (python3-rpm-generators if rpm-build) %endif Provides: %{pkgname}-2to3 = %{version}-%{release} + +%if %{with main_python} Provides: 2to3 = %{version}-%{release} +%endif Conflicts: %{pkgname} < %{version}-%{release} @@ -507,8 +516,10 @@ Summary: A basic graphical development environment for Python Requires: %{pkgname} = %{version}-%{release} Requires: %{pkgname}-tkinter = %{version}-%{release} +%if %{with main_python} Provides: idle3 = %{version}-%{release} Provides: idle = %{version}-%{release} +%endif Provides: %{pkgname}-tools = %{version}-%{release} Provides: %{pkgname}-tools%{?_isa} = %{version}-%{release} @@ -586,11 +597,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 From b071d7f9325a71cf4be586d200ebcb8767bcf8fd Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:23:41 +0000 Subject: [PATCH 033/112] Let there *not* be flatpackage Remove the flatpackage bcond entirely --- python3.10.spec | 90 ++++--------------------------------------------- 1 file changed, 7 insertions(+), 83 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index a58b005..8298d94 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -31,7 +31,6 @@ License: Python # Main Python, i.e. whether this is the main Python version in the distribution # that owns /usr/bin/python3 and other unique paths # This also means the built subpackages are called python3 rather than python3X -# WARNING: This also influences the flatpackage bcond below. # By default, this is determined by the %%__default_python3_pkgversion value %if "%{?__default_python3_pkgversion}" == "%{pybasever}" %bcond_without main_python @@ -39,12 +38,6 @@ License: Python %bcond_with main_python %endif -# Flat package, i.e. no separate subpackages -# Default (in Fedora): don't use the flatpackage structure for Python 3.11 and -# higher, remove the bcond from the spec in the future -# Not supported: Combination of flatpackage enabled and main_python enabled -%bcond_with flatpackage - # When bootstrapping python3, we need to build setuptools. # but setuptools BR python3-devel and that brings in python3-rpm-generators; # python3-rpm-generators needs python3-setuptools, so we cannot have it yet. @@ -76,11 +69,7 @@ License: Python # Extra build for debugging the interpreter or C-API extensions # (the -debug subpackages) -%if %{with flatpackage} -%bcond_with debug_build -%else %bcond_without debug_build -%endif # Support for the GDB debugger %bcond_without gdb_hooks @@ -327,15 +316,7 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # Descriptions, and metadata for subpackages # ========================================== -%if %{without main_python} -# We'll not provide this, on purpose -# No package in Fedora shall ever depend on a alternative Python via this -%global __requires_exclude ^python\\(abi\\) = 3\\..+ -%global __provides_exclude ^python\\(abi\\) = 3\\..+ -%endif # without main_python -# this if branch is ~300 lines long and contains subpackages' definitions -%if %{without flatpackage} %if %{with main_python} # Description for the python3X SRPM only: %description @@ -348,7 +329,7 @@ third-party libraries. Summary: Python %{pybasever} interpreter # In order to support multiple Python interpreters for development purposes, -# packages with the naming scheme flatpackage (e.g. python3.5) exist for +# packages with fully versioned naming scheme (e.g. python3.9*) exist for # non-default versions of Python 3. # For consistency, we provide python3.X from python3 as well. Provides: python%{pybasever} = %{version}-%{release} @@ -372,9 +353,6 @@ Recommends: %{_bindir}/python # 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 # provide and obsolete the previous names. -# - Here are the tags for the nonflat package, regardless if main_python (e.g. -# python3) or not (e.g. python39). For the flat package, the provide is -# repeated many lines later. Provides: python%{pyshortver} = %{version}-%{release} Obsoletes: python%{pyshortver} < %{version}-%{release} @@ -382,7 +360,12 @@ Obsoletes: python%{pyshortver} < %{version}-%{release} # Packages with Python modules in standard locations automatically # depend on python(abi). Provide that here. Provides: python(abi) = %{pybasever} -%endif # with main_python +%else +# We'll not provide this, on purpose +# No package in Fedora shall ever depend on a alternative Python via this +%global __requires_exclude ^python\\(abi\\) = 3\\..+ +%global __provides_exclude ^python\\(abi\\) = 3\\..+ +%endif Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} @@ -595,38 +578,6 @@ The debug runtime additionally supports debug builds of C-API extensions (with the "d" ABI flag) for debugging issues in those extensions. %endif # with debug_build -%else # with flatpackage - -# 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 -# provide and obsolete the previous names. -# - Here are the tags for the flat package. For the nonflat package, the -# provide is repeated many lines above. -Provides: python%{pyshortver} = %{version}-%{release} -Obsoletes: python%{pyshortver} < %{version}-%{release} - -%if %{with rpmwheels} -Requires: %{python_wheel_pkg_prefix}-setuptools-wheel -Requires: %{python_wheel_pkg_prefix}-pip-wheel -%else -Provides: bundled(python3dist(pip)) = %{pip_version} -Provides: bundled(python3dist(setuptools)) = %{setuptools_version} -%endif - -# The zoneinfo module needs tzdata -Requires: tzdata - -# The description for the flat package (SRPM and built) -%description -Python %{pybasever} package for developers. - -This package exists to allow developers to test their code against a newer -version of Python. This is not a full Python stack and if you wish to run -your applications with Python %{pybasever}, update your Fedora to a newer -version once Python %{pybasever} is stable. - -%endif # with flatpackage # ====================================================== # The prep phase of the build: @@ -1130,17 +1081,13 @@ CheckPython optimized %if %{with main_python} -%if %{without flatpackage} %files -n python-unversioned-command -%endif %{_bindir}/python %{_mandir}/*/python.1* %endif -%if %{without flatpackage} %files -n %{pkgname}-libs %doc README.rst -%endif %dir %{pylibdir} %dir %{dynload_dir} @@ -1148,9 +1095,7 @@ CheckPython optimized %license %{pylibdir}/LICENSE.txt %{pylibdir}/lib2to3 -%if %{without flatpackage} %exclude %{pylibdir}/lib2to3/tests -%endif %dir %{pylibdir}/unittest/ %dir %{pylibdir}/unittest/__pycache__/ @@ -1337,10 +1282,8 @@ CheckPython optimized %{pylibdir}/sqlite3/*.py %{pylibdir}/sqlite3/__pycache__/*%{bytecode_suffixes} -%if %{without flatpackage} %exclude %{pylibdir}/turtle.py %exclude %{pylibdir}/__pycache__/turtle*%{bytecode_suffixes} -%endif %{pylibdir}/urllib %{pylibdir}/xml @@ -1366,15 +1309,10 @@ CheckPython optimized %endif -%if %{without flatpackage} %files -n %{pkgname}-devel -%endif - %{pylibdir}/config-%{LDVERSION_optimized}-%{platform_triplet}/* -%if %{without flatpackage} %exclude %{pylibdir}/config-%{LDVERSION_optimized}-%{platform_triplet}/Makefile %exclude %{_includedir}/python%{LDVERSION_optimized}/%{_pyconfig_h} -%endif %{_includedir}/python%{LDVERSION_optimized}/*.h %{_includedir}/python%{LDVERSION_optimized}/internal/ %{_includedir}/python%{LDVERSION_optimized}/cpython/ @@ -1409,10 +1347,7 @@ CheckPython optimized %{_libdir}/pkgconfig/python-%{pybasever}-embed.pc -%if %{without flatpackage} %files -n %{pkgname}-idle -%endif - %if %{with main_python} %{_bindir}/idle* %else @@ -1427,14 +1362,9 @@ CheckPython optimized %{_datadir}/icons/hicolor/*/apps/idle3.* %endif -%if %{without flatpackage} %files -n %{pkgname}-tkinter -%endif - %{pylibdir}/tkinter -%if %{without flatpackage} %exclude %{pylibdir}/tkinter/test -%endif %{dynload_dir}/_tkinter.%{SOABI_optimized}.so %{pylibdir}/turtle.py %{pylibdir}/__pycache__/turtle*%{bytecode_suffixes} @@ -1445,10 +1375,7 @@ CheckPython optimized %{pylibdir}/turtledemo/__pycache__/*%{bytecode_suffixes} -%if %{without flatpackage} %files -n %{pkgname}-test -%endif - %{pylibdir}/ctypes/test %{pylibdir}/distutils/tests %{pylibdir}/sqlite3/test @@ -1471,10 +1398,7 @@ CheckPython optimized # all of the other subpackages %if %{with debug_build} -%if %{without flatpackage} %files -n %{pkgname}-debug -%endif - %if %{with main_python} %{_bindir}/python3-debug %{_bindir}/python-debug From 9fb3dbd8c94a82307bfc4ae4552dc5755adae72f Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:23:42 +0000 Subject: [PATCH 034/112] Obsolete python3.X-foo from individual subpackages e.g. python3-devel now Obsoletes python3.X-devel We are contemplating splitting alternative Pythons into subpackages, so we need to obsolete each of them from the main Python version. Related: rhbz#2063227 --- python3.10.spec | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 8298d94..04e743d 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -152,6 +152,20 @@ License: Python %{warn:Doing a main_python build with wrong %%__default_python3_pkgversion (0%{?__default_python3_pkgversion}, but this is %pyshortver)} %endif +%if %{with main_python} +# To keep the upgrade path clean, we Obsolete python3.X from the python3 +# package and python3.X-foo from individual subpackages. +# Note that using Obsoletes without package version is not standard practice. +# Here we assert that *any* version of the system's default interpreter is +# preferable to an "extra" interpreter. For example, python3-3.6.1 will +# replace python3.6-3.6.2. +%define unversioned_obsoletes_of_python3_X_if_main() %{expand:\ +Obsoletes: python%{pybasever}%{?1:-%{1}}\ +} +%else +%define unversioned_obsoletes_of_python3_X_if_main() %{nil} +%endif + # ======================= # Build-time requirements # ======================= @@ -334,12 +348,8 @@ Summary: Python %{pybasever} interpreter # For consistency, we provide python3.X from python3 as well. Provides: python%{pybasever} = %{version}-%{release} Provides: python%{pybasever}%{?_isa} = %{version}-%{release} -# To keep the upgrade path clean, we Obsolete python3.X. -# Note that using Obsoletes without package version is not standard practice. -# Here we assert that *any* version of the system's default interpreter is -# preferable to an "extra" interpreter. For example, python3-3.6.1 will -# replace python3.6-3.6.2. -Obsoletes: python%{pybasever} + +%unversioned_obsoletes_of_python3_X_if_main # https://fedoraproject.org/wiki/Changes/Move_usr_bin_python_into_separate_package # https://fedoraproject.org/wiki/Changes/Python_means_Python3 @@ -432,6 +442,8 @@ Provides: bundled(python3dist(pip)) = %{pip_version} Provides: bundled(python3dist(setuptools)) = %{setuptools_version} %endif +%unversioned_obsoletes_of_python3_X_if_main libs + # There are files in the standard library that have python shebang. # We've filtered the automatic requirement out so libs are installable without # the main package. This however makes it pulled in by default. @@ -470,6 +482,8 @@ Requires: (python-rpm-macros >= 3.10-9 if rpm-build) Requires: (python3-rpm-macros >= 3.10-9 if rpm-build) Requires: (pyproject-rpm-macros if rpm-build) +%unversioned_obsoletes_of_python3_X_if_main devel + # Python developers are very likely to need pip Recommends: %{pkgname}-pip @@ -499,6 +513,8 @@ Summary: A basic graphical development environment for Python Requires: %{pkgname} = %{version}-%{release} Requires: %{pkgname}-tkinter = %{version}-%{release} +%unversioned_obsoletes_of_python3_X_if_main idle + %if %{with main_python} Provides: idle3 = %{version}-%{release} Provides: idle = %{version}-%{release} @@ -525,6 +541,8 @@ configuration, browsers, and other dialogs. Summary: A GUI toolkit for Python Requires: %{pkgname} = %{version}-%{release} +%unversioned_obsoletes_of_python3_X_if_main tkinter + # The importable module "turtle" is here, so provide python3-turtle. # (We don't provide python3-turtledemo, that's not too useful when imported.) %py_provides %{pkgname}-turtle @@ -539,6 +557,8 @@ Summary: The self-test suite for the main python3 package Requires: %{pkgname} = %{version}-%{release} Requires: %{pkgname}-libs%{?_isa} = %{version}-%{release} +%unversioned_obsoletes_of_python3_X_if_main test + %description -n %{pkgname}-test The self-test suite for the Python interpreter. @@ -561,6 +581,8 @@ Requires: %{pkgname}-test%{?_isa} = %{version}-%{release} Requires: %{pkgname}-tkinter%{?_isa} = %{version}-%{release} Requires: %{pkgname}-idle%{?_isa} = %{version}-%{release} +%unversioned_obsoletes_of_python3_X_if_main debug + %description -n %{pkgname}-debug python3-debug provides a version of the Python runtime with numerous debugging features enabled, aimed at advanced Python users such as developers of Python From 153213a33d6eae5d59962582fada5cfd282ba454 Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:23:42 +0000 Subject: [PATCH 035/112] Add new bcond for python_abi_provides_for_alt_pythons By default enabled on EL, disabled on Fedora --- python3.10.spec | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 04e743d..666fb3d 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -38,6 +38,15 @@ License: Python %bcond_with main_python %endif +# If this is *not* Main Python, should it contain `Provides: python(abi) ...`? +# In Fedora no package shall depend on an alternative Python via this tag, so we do not provide it. +# In ELN/RHEL/CentOS we want to allow building against alternative stacks, so the Provide is enabled. +%if 0%{?fedora} +%bcond_with python_abi_provides_for_alt_pythons +%else +%bcond_without python_abi_provides_for_alt_pythons +%endif + # When bootstrapping python3, we need to build setuptools. # but setuptools BR python3-devel and that brings in python3-rpm-generators; # python3-rpm-generators needs python3-setuptools, so we cannot have it yet. @@ -366,13 +375,12 @@ Recommends: %{_bindir}/python Provides: python%{pyshortver} = %{version}-%{release} Obsoletes: python%{pyshortver} < %{version}-%{release} -%if %{with main_python} +%if %{with main_python} || %{with python_abi_provides_for_alt_pythons} # Packages with Python modules in standard locations automatically # depend on python(abi). Provide that here. Provides: python(abi) = %{pybasever} %else -# We'll not provide this, on purpose -# No package in Fedora shall ever depend on a alternative Python via this +# We exclude the `python(abi)` Provides %global __requires_exclude ^python\\(abi\\) = 3\\..+ %global __provides_exclude ^python\\(abi\\) = 3\\..+ %endif From 861a7a4e00dd7c1285ec293a5f5a055e336d34b5 Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:23:42 +0000 Subject: [PATCH 036/112] Do not Recommend python*-pip if this is not the main_python Because we do not ship pip for alternative stacks (outside of `venv`). --- python3.10.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index 666fb3d..bfc7f82 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -492,8 +492,10 @@ Requires: (pyproject-rpm-macros if rpm-build) %unversioned_obsoletes_of_python3_X_if_main devel +%if %{with main_python} # Python developers are very likely to need pip Recommends: %{pkgname}-pip +%endif %if %{without bootstrap} Requires: (python3-rpm-generators if rpm-build) From c2c15c7b06ab6c3aa1b78dc2500a157d17b6710e Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:24:01 +0000 Subject: [PATCH 037/112] Remove an rpmlintrc rule that was only relevant to flatpackages --- python3.10.rpmlintrc | 3 --- 1 file changed, 3 deletions(-) diff --git a/python3.10.rpmlintrc b/python3.10.rpmlintrc index da5ed3f..5fc9c03 100644 --- a/python3.10.rpmlintrc +++ b/python3.10.rpmlintrc @@ -19,9 +19,6 @@ addFilter(r'self-obsoletion python3\.\d+ obsoletes python3\.\d+') # intentionally hardcoded addFilter(r'hardcoded-library-path in %{_prefix}/lib/(debug/%{_libdir}|python%{pybasever})') -# intentional for our pythonXY package -addFilter(r'python3\.\d+\.[^:]+: (E|W): devel-file-in-non-devel-package') - # we have non binary stuff, python files addFilter(r'only-non-binary-in-usr-lib') From 55d25b67d6153038b462d312e40c083d965ed5dc Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Fri, 29 Apr 2022 10:24:01 +0000 Subject: [PATCH 038/112] Move _sysconfigdata_d_linux*.py to the debug subpackage --- python3.10.spec | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index bfc7f82..a11c7b3 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -1250,6 +1250,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} @@ -1546,6 +1550,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 @@ -1569,6 +1576,9 @@ CheckPython optimized # ====================================================== %changelog +* Sat May 14 2022 Tomas Orsava - 3.10.4-2 +- Move _sysconfigdata_d_linux*.py to the debug subpackage + * Fri Mar 25 2022 Tomáš Hrnčiar - 3.10.4-1 - Update to 3.10.4 From c060b0c436ca81511ba5745be8e23a84d62b41d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 31 May 2022 19:47:45 +0000 Subject: [PATCH 039/112] Don't exclude files that don't exist When built without debug_build, RPM warns: File not found: /builddir/build/BUILDROOT/python3.11-3.11.0~b2-1.fc37.x86_64/usr/lib64/python3.11/_sysconfigdata_d_linux_x86_64-linux-gnu.py File not found: /builddir/build/BUILDROOT/python3.11-3.11.0~b2-1.fc37.x86_64/usr/lib64/python3.11/__pycache__/_sysconfigdata_d_linux_x86_64-linux-gnu.cpython-311*.pyc This might become an error in some distant future. --- python3.10.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index a11c7b3..1bd1166 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -1251,8 +1251,10 @@ CheckPython optimized %dir %{pylibdir}/site-packages/__pycache__/ %{pylibdir}/site-packages/README.txt +%if %{with debug_build} %exclude %{pylibdir}/_sysconfigdata_d_linux_%{platform_triplet}.py %exclude %{pylibdir}/__pycache__/_sysconfigdata_d_linux_%{platform_triplet}%{bytecode_suffixes} +%endif %{pylibdir}/*.py %dir %{pylibdir}/__pycache__/ From 7ff8be2916798a714779fb8c4ef512b7cfcb3fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 31 May 2022 19:47:45 +0000 Subject: [PATCH 040/112] Don't hardcode %{ABIFLAGS_debug} --- python3.10.spec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 1bd1166..f614fae 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -1252,8 +1252,8 @@ CheckPython optimized %{pylibdir}/site-packages/README.txt %if %{with debug_build} -%exclude %{pylibdir}/_sysconfigdata_d_linux_%{platform_triplet}.py -%exclude %{pylibdir}/__pycache__/_sysconfigdata_d_linux_%{platform_triplet}%{bytecode_suffixes} +%exclude %{pylibdir}/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}.py +%exclude %{pylibdir}/__pycache__/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}%{bytecode_suffixes} %endif %{pylibdir}/*.py @@ -1552,8 +1552,8 @@ 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} +%{pylibdir}/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}.py +%{pylibdir}/__pycache__/_sysconfigdata_%{ABIFLAGS_debug}_linux_%{platform_triplet}%{bytecode_suffixes} %endif # with debug_build From 940ad7f7cab48394e84bcefe69979864046da05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Tue, 7 Jun 2022 13:29:54 +0200 Subject: [PATCH 041/112] Update to 3.10.5 --- ...g-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch | 4 ++-- python3.10.spec | 7 +++++-- sources | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) 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 5c814ef..aad6391 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 @@ -60,10 +60,10 @@ index c54806e594..c51de6f4b8 100644 class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py -index 2d89742913..928b3f715d 100644 +index 668126523d..3e14cca8be 100644 --- a/Lib/threading.py +++ b/Lib/threading.py -@@ -1523,29 +1523,20 @@ def _shutdown(): +@@ -1530,29 +1530,20 @@ def _shutdown(): global _SHUTTING_DOWN _SHUTTING_DOWN = True diff --git a/python3.10.spec b/python3.10.spec index f614fae..f6a10b6 100644 --- a/python3.10.spec +++ b/python3.10.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}.4 +%global general_version %{pybasever}.5 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python @@ -1578,6 +1578,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Jun 07 2022 Tomáš Hrnčiar - 3.10.5-1 +- Update to 3.10.5 + * Sat May 14 2022 Tomas Orsava - 3.10.4-2 - Move _sysconfigdata_d_linux*.py to the debug subpackage diff --git a/sources b/sources index 46b98a4..6266f8b 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.4.tar.xz) = 6c9aeecddc55c7896b2e8527fca131c7b2b6127d56ce1a001ccedfebf590334e0c0bb7c517ed3cf1da3c1910e002552b56aa7e03eeb672f42ff0bd8150799113 -SHA512 (Python-3.10.4.tar.xz.asc) = 699e37bf09067083af159e3734b38c952bdc75432c8abfb7a7b8cce7ca975038da37490abeb5c13befd2dacb84a5341ad30de5d0a63d35af5c512215744f4d6d +SHA512 (Python-3.10.5.tar.xz) = aa7f58a9b31de9824185b3e7bfa7da0dcf64ae9e89840664eae9d98d9048a650fa012cd5b873a62ff44b65b856db86f095c4003117406ec5e9583ec5f7e78e90 +SHA512 (Python-3.10.5.tar.xz.asc) = 72d0ab09900e2a10b85ccac804efd5536251152798e7347576e0e28bff4ab4a84b08d646329b225f9949047586686f9f4e7f05652526657a0948951b739c14e0 From 14dceddf563016a3e55091c54eb3df3159362b17 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 9 Jun 2022 15:46:59 +0200 Subject: [PATCH 042/112] Security fix for CVE-2015-20107 Resolves: rhbz#2075390 --- 00382-cve-2015-20107.patch | 150 +++++++++++++++++++++++++++++++++++++ python3.10.spec | 16 +++- 2 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 00382-cve-2015-20107.patch diff --git a/00382-cve-2015-20107.patch b/00382-cve-2015-20107.patch new file mode 100644 index 0000000..dd7992e --- /dev/null +++ b/00382-cve-2015-20107.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Fri, 3 Jun 2022 11:43:35 +0200 +Subject: [PATCH] 00382: CVE-2015-20107 + +Make mailcap refuse to match unsafe filenames/types/params (GH-91993) + +Upstream: https://github.com/python/cpython/issues/68966 + +Tracker bug: https://bugzilla.redhat.com/show_bug.cgi?id=2075390 +--- + Doc/library/mailcap.rst | 12 +++++++++ + Lib/mailcap.py | 26 +++++++++++++++++-- + Lib/test/test_mailcap.py | 8 ++++-- + ...2-04-27-18-25-30.gh-issue-68966.gjS8zs.rst | 4 +++ + 4 files changed, 46 insertions(+), 4 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst + +diff --git a/Doc/library/mailcap.rst b/Doc/library/mailcap.rst +index e2e5bb3445..2bc00195cd 100644 +--- a/Doc/library/mailcap.rst ++++ b/Doc/library/mailcap.rst +@@ -60,6 +60,18 @@ standard. However, mailcap files are supported on most Unix systems. + use) to determine whether or not the mailcap line applies. :func:`findmatch` + will automatically check such conditions and skip the entry if the check fails. + ++ .. versionchanged:: 3.11 ++ ++ To prevent security issues with shell metacharacters (symbols that have ++ special effects in a shell command line), ``findmatch`` will refuse ++ to inject ASCII characters other than alphanumerics and ``@+=:,./-_`` ++ into the returned command line. ++ ++ If a disallowed character appears in *filename*, ``findmatch`` will always ++ return ``(None, None)`` as if no entry was found. ++ If such a character appears elsewhere (a value in *plist* or in *MIMEtype*), ++ ``findmatch`` will ignore all mailcap entries which use that value. ++ A :mod:`warning ` will be raised in either case. + + .. function:: getcaps() + +diff --git a/Lib/mailcap.py b/Lib/mailcap.py +index ae416a8e9f..444c6408b5 100644 +--- a/Lib/mailcap.py ++++ b/Lib/mailcap.py +@@ -2,6 +2,7 @@ + + import os + import warnings ++import re + + __all__ = ["getcaps","findmatch"] + +@@ -13,6 +14,11 @@ def lineno_sort_key(entry): + else: + return 1, 0 + ++_find_unsafe = re.compile(r'[^\xa1-\U0010FFFF\w@+=:,./-]').search ++ ++class UnsafeMailcapInput(Warning): ++ """Warning raised when refusing unsafe input""" ++ + + # Part 1: top-level interface. + +@@ -165,15 +171,22 @@ def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]): + entry to use. + + """ ++ if _find_unsafe(filename): ++ msg = "Refusing to use mailcap with filename %r. Use a safe temporary filename." % (filename,) ++ warnings.warn(msg, UnsafeMailcapInput) ++ return None, None + entries = lookup(caps, MIMEtype, key) + # XXX This code should somehow check for the needsterminal flag. + for e in entries: + if 'test' in e: + test = subst(e['test'], filename, plist) ++ if test is None: ++ continue + if test and os.system(test) != 0: + continue + command = subst(e[key], MIMEtype, filename, plist) +- return command, e ++ if command is not None: ++ return command, e + return None, None + + def lookup(caps, MIMEtype, key=None): +@@ -206,6 +219,10 @@ def subst(field, MIMEtype, filename, plist=[]): + elif c == 's': + res = res + filename + elif c == 't': ++ if _find_unsafe(MIMEtype): ++ msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,) ++ warnings.warn(msg, UnsafeMailcapInput) ++ return None + res = res + MIMEtype + elif c == '{': + start = i +@@ -213,7 +230,12 @@ def subst(field, MIMEtype, filename, plist=[]): + i = i+1 + name = field[start:i] + i = i+1 +- res = res + findparam(name, plist) ++ param = findparam(name, plist) ++ if _find_unsafe(param): ++ msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name) ++ warnings.warn(msg, UnsafeMailcapInput) ++ return None ++ res = res + param + # XXX To do: + # %n == number of parts if type is multipart/* + # %F == list of alternating type and filename for parts +diff --git a/Lib/test/test_mailcap.py b/Lib/test/test_mailcap.py +index ef9cad498a..32f07ab290 100644 +--- a/Lib/test/test_mailcap.py ++++ b/Lib/test/test_mailcap.py +@@ -123,7 +123,8 @@ def test_subst(self): + (["", "audio/*", "foo.txt"], ""), + (["echo foo", "audio/*", "foo.txt"], "echo foo"), + (["echo %s", "audio/*", "foo.txt"], "echo foo.txt"), +- (["echo %t", "audio/*", "foo.txt"], "echo audio/*"), ++ (["echo %t", "audio/*", "foo.txt"], None), ++ (["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"), + (["echo \\%t", "audio/*", "foo.txt"], "echo %t"), + (["echo foo", "audio/*", "foo.txt", plist], "echo foo"), + (["echo %{total}", "audio/*", "foo.txt", plist], "echo 3") +@@ -207,7 +208,10 @@ def test_findmatch(self): + ('"An audio fragment"', audio_basic_entry)), + ([c, "audio/*"], + {"filename": fname}, +- ("/usr/local/bin/showaudio audio/*", audio_entry)), ++ (None, None)), ++ ([c, "audio/wav"], ++ {"filename": fname}, ++ ("/usr/local/bin/showaudio audio/wav", audio_entry)), + ([c, "message/external-body"], + {"plist": plist}, + ("showexternal /dev/null default john python.org /tmp foo bar", message_entry)) +diff --git a/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst b/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst +new file mode 100644 +index 0000000000..da81a1f699 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst +@@ -0,0 +1,4 @@ ++The deprecated mailcap module now refuses to inject unsafe text (filenames, ++MIME types, parameters) into shell commands. Instead of using such text, it ++will warn and act as if a match was not found (or for test commands, as if ++the test failed). diff --git a/python3.10.spec b/python3.10.spec index f6a10b6..8cf67df 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -321,6 +321,16 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00382 # 9e275dcdf3934b827994ecc3247d583d5bab7985 +# CVE-2015-20107 +# +# Make mailcap refuse to match unsafe filenames/types/params (GH-91993) +# +# Upstream: https://github.com/python/cpython/issues/68966 +# +# Tracker bug: https://bugzilla.redhat.com/show_bug.cgi?id=2075390 +Patch382: 00382-cve-2015-20107.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1578,6 +1588,10 @@ CheckPython optimized # ====================================================== %changelog +* Thu Jun 09 2022 Charalampos Stratakis - 3.10.5-2 +- Security fix for CVE-2015-20107 +Resolves: rhbz#2075390 + * Tue Jun 07 2022 Tomáš Hrnčiar - 3.10.5-1 - Update to 3.10.5 From 563252ba42126d81aabcfe5ec0995dc23682923d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Mon, 13 Jun 2022 11:49:58 +0200 Subject: [PATCH 043/112] Rebuilt for Python 3.11 --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 8cf67df..3d059a4 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python @@ -1588,6 +1588,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Jun 13 2022 Tomáš Hrnčiar - 3.10.5-3 +- Rebuilt for Python 3.11 + * Thu Jun 09 2022 Charalampos Stratakis - 3.10.5-2 - Security fix for CVE-2015-20107 Resolves: rhbz#2075390 From 3c729ba430f134be7c325ddf51fc749851bfd6f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 20 Jun 2022 11:33:12 +0000 Subject: [PATCH 044/112] rpminspect: exclude the debug build from annocheck entirely --- rpminspect.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rpminspect.yaml b/rpminspect.yaml index 213d92c..a111efb 100644 --- a/rpminspect.yaml +++ b/rpminspect.yaml @@ -9,6 +9,13 @@ badfuncs: ignore: - /usr/lib*/python*/lib-dynload/_socket.* +# exclude the debug build from annocheck entirely +annocheck: + ignore: + - /usr/bin/python*d + - /usr/lib*/libpython*d.so.1.0 + - /usr/lib*/python*/lib-dynload/*.cpython-*d-*-*-*.so + # don't report changed content of compiled files # that is expected with every toolchain update and not reproducible yet changedfiles: From cd753a02ba1c4afd33f01eb18b14926b0be1a641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Mon, 20 Jun 2022 09:13:11 +0200 Subject: [PATCH 045/112] Fedora CI: Make CI tests compatible with both main and non-main Python --- tests/tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/tests.yml b/tests/tests.yml index c2f2df4..5a1bf68 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -26,16 +26,16 @@ run: VERSION=3.10 METHOD=virtualenv ./venv.sh - debugsmoke: dir: python/smoke - run: PYTHON=python3-debug TOX=false VERSION=3.10 ./venv.sh + run: PYTHON=python3.10d TOX=false VERSION=3.10 ./venv.sh - selftest: dir: python/selftest run: VERSION=3.10 X="" ./parallel.sh - debugtest: dir: python/selftest - run: VERSION=3.10 PYTHON=python3-debug X="" ./parallel.sh + run: VERSION=3.10 PYTHON=python3.10d X="" ./parallel.sh - debugflags: dir: python/flags - run: python3-debug ./assertflags.py -O0 + run: python3.10d ./assertflags.py -O0 - marshalparser: dir: python/marshalparser run: VERSION=3.10 SAMPLE=10 test_marshalparser_compatibility.sh @@ -43,10 +43,10 @@ - gcc # for extension building in venv and selftest - gdb # for test_gdb - python3.10 # the test subject - - python3-debug # for leak testing - - python3-devel # for extension building in venv and selftest - - python3-tkinter # for selftest - - python3-test # for selftest + - python3.10-debug # for leak testing + - python3.10-devel # for extension building in venv and selftest + - python3.10-tkinter # for selftest + - python3.10-test # for selftest - tox # for venv tests - virtualenv # for virtualenv tests - glibc-all-langpacks # for locale tests From 4225d6644ba3308638bb747fcab0f430bed40bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 8 Jul 2022 10:27:42 +0000 Subject: [PATCH 046/112] CI tests config: Define and reuse the pybasever variable This will make future changes easier to backport to other Python versions. Note that with jinja2 expressions, we need to quote them to preserve valid yaml, see: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#when-to-quote-variables-a-yaml-gotcha --- tests/tests.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/tests.yml b/tests/tests.yml index 5a1bf68..460b4a1 100644 --- a/tests/tests.yml +++ b/tests/tests.yml @@ -15,38 +15,39 @@ repositories: - repo: "https://src.fedoraproject.org/tests/python.git" dest: "python" + pybasever: "3.10" tests: - rpm_qa: run: rpm -qa - smoke: dir: python/smoke - run: VERSION=3.10 ./venv.sh + run: "VERSION={{ pybasever }} ./venv.sh" - smoke_virtualenv: dir: python/smoke - run: VERSION=3.10 METHOD=virtualenv ./venv.sh + run: "VERSION={{ pybasever }} METHOD=virtualenv ./venv.sh" - debugsmoke: dir: python/smoke - run: PYTHON=python3.10d TOX=false VERSION=3.10 ./venv.sh + run: "PYTHON=python{{ pybasever }}d TOX=false VERSION={{ pybasever }} ./venv.sh" - selftest: dir: python/selftest - run: VERSION=3.10 X="" ./parallel.sh + run: "VERSION={{ pybasever }} X='' ./parallel.sh" - debugtest: dir: python/selftest - run: VERSION=3.10 PYTHON=python3.10d X="" ./parallel.sh + run: "VERSION={{ pybasever }} PYTHON=python{{ pybasever }}d X='' ./parallel.sh" - debugflags: dir: python/flags - run: python3.10d ./assertflags.py -O0 + run: "python{{ pybasever }}d ./assertflags.py -O0" - marshalparser: dir: python/marshalparser - run: VERSION=3.10 SAMPLE=10 test_marshalparser_compatibility.sh + run: "VERSION={{ pybasever }} SAMPLE=10 test_marshalparser_compatibility.sh" required_packages: - gcc # for extension building in venv and selftest - gdb # for test_gdb - - python3.10 # the test subject - - python3.10-debug # for leak testing - - python3.10-devel # for extension building in venv and selftest - - python3.10-tkinter # for selftest - - python3.10-test # for selftest + - "python{{ pybasever }}" # the test subject + - "python{{ pybasever }}-debug" # for leak testing + - "python{{ pybasever }}-devel" # for extension building in venv and selftest + - "python{{ pybasever }}-tkinter" # for selftest + - "python{{ pybasever }}-test" # for selftest - tox # for venv tests - virtualenv # for virtualenv tests - glibc-all-langpacks # for locale tests From ce2b654098ef444a911cd810408f93e7e43a9ea3 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 22 Jul 2022 23:46:44 +0000 Subject: [PATCH 047/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 3d059a4..d3f6c50 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python @@ -1588,6 +1588,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jul 22 2022 Fedora Release Engineering - 3.10.5-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + * Mon Jun 13 2022 Tomáš Hrnčiar - 3.10.5-3 - Rebuilt for Python 3.11 From f5d6ae420d6934788e2425d56ebefac722ae8c5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Tue, 2 Aug 2022 14:38:43 +0200 Subject: [PATCH 048/112] Update to 3.10.6 --- 00251-change-user-install-location.patch | 2 +- python3.10.spec | 11 +++++++---- sources | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index ac6901d..1681e82 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -90,7 +90,7 @@ index daf9f00006..40e4edf0ae 100644 # NOTE: site.py has copy of this function. # Sync it when modify this function. diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py -index 9408657c91..fd49b2bcce 100644 +index 5ee9839c04..4cc7b13719 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -263,7 +263,7 @@ def test_get_config_h_filename(self): diff --git a/python3.10.spec b/python3.10.spec index d3f6c50..3d175a9 100644 --- a/python3.10.spec +++ b/python3.10.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}.5 +%global general_version %{pybasever}.6 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 1%{?dist} License: Python @@ -67,8 +67,8 @@ License: Python # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 22.0.4 -%global setuptools_version 58.1.0 +%global pip_version 22.2.1 +%global setuptools_version 63.2.0 # Expensive optimizations (mainly, profile-guided optimizations) %bcond_without optimizations @@ -1588,6 +1588,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Aug 02 2022 Tomáš Hrnčiar - 3.10.6-1 +- Update to 3.10.6 + * Fri Jul 22 2022 Fedora Release Engineering - 3.10.5-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild diff --git a/sources b/sources index 6266f8b..0c2ea47 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.5.tar.xz) = aa7f58a9b31de9824185b3e7bfa7da0dcf64ae9e89840664eae9d98d9048a650fa012cd5b873a62ff44b65b856db86f095c4003117406ec5e9583ec5f7e78e90 -SHA512 (Python-3.10.5.tar.xz.asc) = 72d0ab09900e2a10b85ccac804efd5536251152798e7347576e0e28bff4ab4a84b08d646329b225f9949047586686f9f4e7f05652526657a0948951b739c14e0 +SHA512 (Python-3.10.6.tar.xz) = f2bf424bf4f4caa524ee1248b431e8e06d0745c3fc3ba457710d75f3698e653733feb4b059cd124f1de2a9e851c30d847f567aa47abef12898c9dc8a6507b476 +SHA512 (Python-3.10.6.tar.xz.asc) = 9288e2f62f2e8c8208ad176372261545a64e675d737bb616403bcd888bc91177909257632e4cc0b5d688d612bea38a274030ec6989dc7d56c03064e32ad9903e From 38f9dd159059a1fbadb6c251d521e299d54cee81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 22 Aug 2022 12:03:59 +0200 Subject: [PATCH 049/112] Don't use custom installation schemes --- 00251-change-user-install-location.patch | 173 ++++++++++++++++++----- python3.10.spec | 30 ++-- 2 files changed, 152 insertions(+), 51 deletions(-) diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index 1681e82..dc9c257 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -1,37 +1,65 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lumir Balhar +From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 15 Feb 2021 12:19:27 +0100 Subject: [PATCH] 00251: Change user install location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -Change the values of sysconfig's "posix_prefix" install scheme to /usr/local -when RPM build or venv/virtualenv is not detected, -to make pip, sysconfig and distutils install into an isolated location. +Set values of base and platbase in sysconfig from /usr +to /usr/local when RPM build is not detected +to make pip and similar tools install into separate location. -The original values are saved as an additional "rpm_prefix" install scheme. - -The site module adds the /usr/local paths to sys.path when site packages are -enabled and RPM build is not detected. +Set values of prefix and exec_prefix in distutils install command +to /usr/local if executable is /usr/bin/python* and RPM build +is not detected to make distutils and pypa/distutils install into separate location. Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe +Downstream only. -Rewrote in Fedora 36+ to patch sysconfig instead of distutils, -see https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/104 +We've tried to rework in Fedora 36/Python 3.10 to follow https://bugs.python.org/issue43976 +but we have identified serious problems with that approach, +see https://bugzilla.redhat.com/2026979 or https://bugzilla.redhat.com/2097183 -Downstream only for now, waiting for https://bugs.python.org/issue43976 +pypa/distutils integration: https://github.com/pypa/distutils/pull/70 Co-authored-by: Petr Viktorin Co-authored-by: Miro Hrončok Co-authored-by: Michal Cyprian Co-authored-by: Lumír Balhar --- - Lib/site.py | 9 ++++++++- - Lib/sysconfig.py | 25 +++++++++++++++++++++++++ - Lib/test/test_sysconfig.py | 4 +++- - 3 files changed, 36 insertions(+), 2 deletions(-) + Lib/distutils/command/install.py | 8 +++-- + Lib/site.py | 9 +++++- + Lib/sysconfig.py | 53 +++++++++++++++++++++++++++++++- + Lib/test/test_sysconfig.py | 17 ++++++++-- + 4 files changed, 81 insertions(+), 6 deletions(-) +diff --git a/Lib/distutils/command/install.py b/Lib/distutils/command/install.py +index 01d5331a63..79f70f0de4 100644 +--- a/Lib/distutils/command/install.py ++++ b/Lib/distutils/command/install.py +@@ -159,6 +159,8 @@ class install(Command): + + negative_opt = {'no-compile' : 'compile'} + ++ # Allow Fedora to add components to the prefix ++ _prefix_addition = getattr(sysconfig, '_prefix_addition', '') + + def initialize_options(self): + """Initializes options.""" +@@ -441,8 +443,10 @@ def finalize_unix(self): + raise DistutilsOptionError( + "must not supply exec-prefix without prefix") + +- self.prefix = os.path.normpath(sys.prefix) +- self.exec_prefix = os.path.normpath(sys.exec_prefix) ++ self.prefix = ( ++ os.path.normpath(sys.prefix) + self._prefix_addition) ++ self.exec_prefix = ( ++ os.path.normpath(sys.exec_prefix) + self._prefix_addition) + + else: + if self.exec_prefix is None: diff --git a/Lib/site.py b/Lib/site.py index 939893eb5e..d1316c3355 100644 --- a/Lib/site.py @@ -54,46 +82,113 @@ index 939893eb5e..d1316c3355 100644 if os.path.isdir(sitedir): addsitedir(sitedir, known_paths) diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py -index daf9f00006..40e4edf0ae 100644 +index daf9f00006..10368c92a7 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py -@@ -58,6 +58,31 @@ +@@ -58,6 +58,16 @@ }, } -+# backup the original posix_prefix as rpm_prefix -+# RPM packages use it and we need to be able to read it even when changed ++# For a brief period of time in the Fedora 36 life cycle, ++# this installation scheme existed and was documented in the release notes. ++# For backwards compatibility, we keep it here (at least on 3.10 and 3.11). +_INSTALL_SCHEMES['rpm_prefix'] = _INSTALL_SCHEMES['posix_prefix'] +# Virtualenv >= 20.10.0 favors the "venv" scheme over the defaults when creating virtual environments. +# See: https://github.com/pypa/virtualenv/commit/8da79db86d8a5c74d03667a40e64ff832076445e +# See: https://bugs.python.org/issue45413 -+# "venv" should be the same as the unpatched posix_prefix for us, ++# "venv" should be the same as the posix_prefix for us, +# so new virtual environments aren't created with paths like venv/local/bin/python. +_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_prefix'] -+ -+if (not (hasattr(sys, 'real_prefix') or -+ sys.prefix != sys.base_prefix) and -+ 'RPM_BUILD_ROOT' not in os.environ): -+ _INSTALL_SCHEMES['posix_prefix'] = { -+ 'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}', -+ 'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}', -+ 'purelib': '{base}/local/lib/python{py_version_short}/site-packages', -+ 'platlib': '{platbase}/local/{platlibdir}/python{py_version_short}/site-packages', -+ 'include': -+ '{installed_base}/include/python{py_version_short}{abiflags}', -+ 'platinclude': -+ '{installed_platbase}/include/python{py_version_short}{abiflags}', -+ 'scripts': '{base}/local/bin', -+ 'data': '{base}/local', -+ } # NOTE: site.py has copy of this function. # Sync it when modify this function. +@@ -117,6 +127,19 @@ def joinuser(*args): + }, + } + ++# This is used by distutils.command.install in the stdlib ++# as well as pypa/distutils (e.g. bundled in setuptools). ++# The self.prefix value is set to sys.prefix + /local/ ++# if neither RPM build nor virtual environment is ++# detected to make distutils install packages ++# into the separate location. ++# https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe ++if (not (hasattr(sys, 'real_prefix') or ++ sys.prefix != sys.base_prefix) and ++ 'RPM_BUILD_ROOT' not in os.environ): ++ _prefix_addition = '/local' ++ ++ + _SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include', + 'scripts', 'data') + +@@ -211,11 +234,39 @@ def _extend_dict(target_dict, other_dict): + target_dict[key] = value + + ++_CONFIG_VARS_LOCAL = None ++ ++ ++def _config_vars_local(): ++ # This function returns the config vars with prefixes amended to /usr/local ++ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe ++ global _CONFIG_VARS_LOCAL ++ if _CONFIG_VARS_LOCAL is None: ++ _CONFIG_VARS_LOCAL = dict(get_config_vars()) ++ _CONFIG_VARS_LOCAL['base'] = '/usr/local' ++ _CONFIG_VARS_LOCAL['platbase'] = '/usr/local' ++ return _CONFIG_VARS_LOCAL ++ ++ + def _expand_vars(scheme, vars): + res = {} + if vars is None: + vars = {} +- _extend_dict(vars, get_config_vars()) ++ ++ # when we are not in a virtual environment or an RPM build ++ # we change '/usr' to '/usr/local' ++ # to avoid surprises, we explicitly check for the /usr/ prefix ++ # Python virtual environments have different prefixes ++ # we only do this for posix_prefix, not to mangle the venv scheme ++ # posix_prefix is used by sudo pip install ++ # we only change the defaults here, so explicit --prefix will take precedence ++ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe ++ if (scheme == 'posix_prefix' and ++ _PREFIX == '/usr' and ++ 'RPM_BUILD_ROOT' not in os.environ): ++ _extend_dict(vars, _config_vars_local()) ++ else: ++ _extend_dict(vars, get_config_vars()) + + for key, value in _INSTALL_SCHEMES[scheme].items(): + if os.name in ('posix', 'nt'): diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py -index 5ee9839c04..4cc7b13719 100644 +index 5ee9839c04..16e92ca86f 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py -@@ -263,7 +263,7 @@ def test_get_config_h_filename(self): +@@ -105,8 +105,19 @@ def test_get_path(self): + for scheme in _INSTALL_SCHEMES: + for name in _INSTALL_SCHEMES[scheme]: + expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars) ++ tested = get_path(name, scheme) ++ # https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe ++ if tested.startswith('/usr/local'): ++ # /usr/local should only be used in posix_prefix ++ self.assertEqual(scheme, 'posix_prefix') ++ # Fedora CI runs tests for venv and virtualenv that check for other prefixes ++ self.assertEqual(sys.prefix, '/usr') ++ # When building the RPM of Python, %check runs this with RPM_BUILD_ROOT set ++ # Fedora CI runs this with RPM_BUILD_ROOT unset ++ self.assertNotIn('RPM_BUILD_ROOT', os.environ) ++ tested = tested.replace('/usr/local', '/usr') + self.assertEqual( +- os.path.normpath(get_path(name, scheme)), ++ os.path.normpath(tested), + os.path.normpath(expected), + ) + +@@ -263,7 +274,7 @@ def test_get_config_h_filename(self): self.assertTrue(os.path.isfile(config_h), config_h) def test_get_scheme_names(self): @@ -102,7 +197,7 @@ index 5ee9839c04..4cc7b13719 100644 if HAS_USER_BASE: wanted.extend(['nt_user', 'osx_framework_user', 'posix_user']) self.assertEqual(get_scheme_names(), tuple(sorted(wanted))) -@@ -274,6 +274,8 @@ def test_symlink(self): # Issue 7880 +@@ -274,6 +285,8 @@ def test_symlink(self): # Issue 7880 cmd = "-c", "import sysconfig; print(sysconfig.get_platform())" self.assertEqual(py.call_real(*cmd), py.call_link(*cmd)) diff --git a/python3.10.spec b/python3.10.spec index 3d175a9..fb878d9 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python @@ -276,24 +276,25 @@ Source11: idle3.appdata.xml # Was Patch0 in ivazquez' python3000 specfile Patch1: 00001-rpath.patch -# 00251 # 531494a5ded29dad59f617304dab4eb8b7f80b0b +# 00251 # 8448a0d6edd44d0818b8c02dc603b769b5363e5b # Change user install location # -# Change the values of sysconfig's "posix_prefix" install scheme to /usr/local -# when RPM build or venv/virtualenv is not detected, -# to make pip, sysconfig and distutils install into an isolated location. +# Set values of base and platbase in sysconfig from /usr +# to /usr/local when RPM build is not detected +# to make pip and similar tools install into separate location. # -# The original values are saved as an additional "rpm_prefix" install scheme. -# -# The site module adds the /usr/local paths to sys.path when site packages are -# enabled and RPM build is not detected. +# Set values of prefix and exec_prefix in distutils install command +# to /usr/local if executable is /usr/bin/python* and RPM build +# is not detected to make distutils and pypa/distutils install into separate location. # # Fedora Change: https://fedoraproject.org/wiki/Changes/Making_sudo_pip_safe +# Downstream only. # -# Rewrote in Fedora 36+ to patch sysconfig instead of distutils, -# see https://discuss.python.org/t/pep-632-deprecate-distutils-module/5134/104 +# We've tried to rework in Fedora 36/Python 3.10 to follow https://bugs.python.org/issue43976 +# but we have identified serious problems with that approach, +# see https://bugzilla.redhat.com/2026979 or https://bugzilla.redhat.com/2097183 # -# Downstream only for now, waiting for https://bugs.python.org/issue43976 +# pypa/distutils integration: https://github.com/pypa/distutils/pull/70 Patch251: 00251-change-user-install-location.patch # 00328 # 318e500c98f5e59eb1f23e0fcd32db69b9bd17e1 @@ -1588,6 +1589,11 @@ CheckPython optimized # ====================================================== %changelog +* Mon Aug 22 2022 Miro Hrončok - 3.10.6-2 +- Don't use custom installation schemes +- Fixes rhbz#2026979 +- Fixes rhbz#2097183 + * Tue Aug 02 2022 Tomáš Hrnčiar - 3.10.6-1 - Update to 3.10.6 From 380974854346ea41bd97dbda24392c7fc183de55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 7 Sep 2022 16:00:03 +0200 Subject: [PATCH 050/112] Update to 3.10.7, with security fix for CVE-2020-10735 --- ...hutdown-for-the-main-thread-gh-28549-gh-28589.patch | 2 +- python3.10.spec | 10 +++++++--- sources | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) 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 aad6391..7ab6c6c 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 @@ -60,7 +60,7 @@ index c54806e594..c51de6f4b8 100644 class ThreadJoinOnShutdown(BaseTestCase): diff --git a/Lib/threading.py b/Lib/threading.py -index 668126523d..3e14cca8be 100644 +index 62f49c05cd..433aa11212 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -1530,29 +1530,20 @@ def _shutdown(): diff --git a/python3.10.spec b/python3.10.spec index fb878d9..40297fd 100644 --- a/python3.10.spec +++ b/python3.10.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}.6 +%global general_version %{pybasever}.7 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python @@ -67,7 +67,7 @@ License: Python # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 22.2.1 +%global pip_version 22.2.2 %global setuptools_version 63.2.0 # Expensive optimizations (mainly, profile-guided optimizations) @@ -1589,6 +1589,10 @@ CheckPython optimized # ====================================================== %changelog +* Wed Sep 07 2022 Miro Hrončok - 3.10.7-1 +- Update to 3.10.7 +- Contains security fix for CVE-2020-10735 + * Mon Aug 22 2022 Miro Hrončok - 3.10.6-2 - Don't use custom installation schemes - Fixes rhbz#2026979 diff --git a/sources b/sources index 0c2ea47..9efa146 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.6.tar.xz) = f2bf424bf4f4caa524ee1248b431e8e06d0745c3fc3ba457710d75f3698e653733feb4b059cd124f1de2a9e851c30d847f567aa47abef12898c9dc8a6507b476 -SHA512 (Python-3.10.6.tar.xz.asc) = 9288e2f62f2e8c8208ad176372261545a64e675d737bb616403bcd888bc91177909257632e4cc0b5d688d612bea38a274030ec6989dc7d56c03064e32ad9903e +SHA512 (Python-3.10.7.tar.xz) = dc3432d72ee7382617318c9645204876d13bb61d4caf3fbbb65e6b14897261123c743049657c95e159e5566daf4dcde613d2e393f025de758f610b44eb958313 +SHA512 (Python-3.10.7.tar.xz.asc) = a65d152d87870de763de3384a1c0ff0309068a2af0fcdfa39a6f968a52b59c56229553cf6a955ec0af1d3db5bf4641c4e91d6150764548d2e9fb0e9a01ab759d From 3fef586c930bcb62f30077b8f1cc81a43e98fdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 12 Oct 2022 15:44:08 +0200 Subject: [PATCH 051/112] Update to 3.10.8 Patch 382 was merged upstream. --- 00382-cve-2015-20107.patch | 150 ------------------------------------- python3.10.spec | 15 +--- sources | 4 +- 3 files changed, 6 insertions(+), 163 deletions(-) delete mode 100644 00382-cve-2015-20107.patch diff --git a/00382-cve-2015-20107.patch b/00382-cve-2015-20107.patch deleted file mode 100644 index dd7992e..0000000 --- a/00382-cve-2015-20107.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Fri, 3 Jun 2022 11:43:35 +0200 -Subject: [PATCH] 00382: CVE-2015-20107 - -Make mailcap refuse to match unsafe filenames/types/params (GH-91993) - -Upstream: https://github.com/python/cpython/issues/68966 - -Tracker bug: https://bugzilla.redhat.com/show_bug.cgi?id=2075390 ---- - Doc/library/mailcap.rst | 12 +++++++++ - Lib/mailcap.py | 26 +++++++++++++++++-- - Lib/test/test_mailcap.py | 8 ++++-- - ...2-04-27-18-25-30.gh-issue-68966.gjS8zs.rst | 4 +++ - 4 files changed, 46 insertions(+), 4 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst - -diff --git a/Doc/library/mailcap.rst b/Doc/library/mailcap.rst -index e2e5bb3445..2bc00195cd 100644 ---- a/Doc/library/mailcap.rst -+++ b/Doc/library/mailcap.rst -@@ -60,6 +60,18 @@ standard. However, mailcap files are supported on most Unix systems. - use) to determine whether or not the mailcap line applies. :func:`findmatch` - will automatically check such conditions and skip the entry if the check fails. - -+ .. versionchanged:: 3.11 -+ -+ To prevent security issues with shell metacharacters (symbols that have -+ special effects in a shell command line), ``findmatch`` will refuse -+ to inject ASCII characters other than alphanumerics and ``@+=:,./-_`` -+ into the returned command line. -+ -+ If a disallowed character appears in *filename*, ``findmatch`` will always -+ return ``(None, None)`` as if no entry was found. -+ If such a character appears elsewhere (a value in *plist* or in *MIMEtype*), -+ ``findmatch`` will ignore all mailcap entries which use that value. -+ A :mod:`warning ` will be raised in either case. - - .. function:: getcaps() - -diff --git a/Lib/mailcap.py b/Lib/mailcap.py -index ae416a8e9f..444c6408b5 100644 ---- a/Lib/mailcap.py -+++ b/Lib/mailcap.py -@@ -2,6 +2,7 @@ - - import os - import warnings -+import re - - __all__ = ["getcaps","findmatch"] - -@@ -13,6 +14,11 @@ def lineno_sort_key(entry): - else: - return 1, 0 - -+_find_unsafe = re.compile(r'[^\xa1-\U0010FFFF\w@+=:,./-]').search -+ -+class UnsafeMailcapInput(Warning): -+ """Warning raised when refusing unsafe input""" -+ - - # Part 1: top-level interface. - -@@ -165,15 +171,22 @@ def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]): - entry to use. - - """ -+ if _find_unsafe(filename): -+ msg = "Refusing to use mailcap with filename %r. Use a safe temporary filename." % (filename,) -+ warnings.warn(msg, UnsafeMailcapInput) -+ return None, None - entries = lookup(caps, MIMEtype, key) - # XXX This code should somehow check for the needsterminal flag. - for e in entries: - if 'test' in e: - test = subst(e['test'], filename, plist) -+ if test is None: -+ continue - if test and os.system(test) != 0: - continue - command = subst(e[key], MIMEtype, filename, plist) -- return command, e -+ if command is not None: -+ return command, e - return None, None - - def lookup(caps, MIMEtype, key=None): -@@ -206,6 +219,10 @@ def subst(field, MIMEtype, filename, plist=[]): - elif c == 's': - res = res + filename - elif c == 't': -+ if _find_unsafe(MIMEtype): -+ msg = "Refusing to substitute MIME type %r into a shell command." % (MIMEtype,) -+ warnings.warn(msg, UnsafeMailcapInput) -+ return None - res = res + MIMEtype - elif c == '{': - start = i -@@ -213,7 +230,12 @@ def subst(field, MIMEtype, filename, plist=[]): - i = i+1 - name = field[start:i] - i = i+1 -- res = res + findparam(name, plist) -+ param = findparam(name, plist) -+ if _find_unsafe(param): -+ msg = "Refusing to substitute parameter %r (%s) into a shell command" % (param, name) -+ warnings.warn(msg, UnsafeMailcapInput) -+ return None -+ res = res + param - # XXX To do: - # %n == number of parts if type is multipart/* - # %F == list of alternating type and filename for parts -diff --git a/Lib/test/test_mailcap.py b/Lib/test/test_mailcap.py -index ef9cad498a..32f07ab290 100644 ---- a/Lib/test/test_mailcap.py -+++ b/Lib/test/test_mailcap.py -@@ -123,7 +123,8 @@ def test_subst(self): - (["", "audio/*", "foo.txt"], ""), - (["echo foo", "audio/*", "foo.txt"], "echo foo"), - (["echo %s", "audio/*", "foo.txt"], "echo foo.txt"), -- (["echo %t", "audio/*", "foo.txt"], "echo audio/*"), -+ (["echo %t", "audio/*", "foo.txt"], None), -+ (["echo %t", "audio/wav", "foo.txt"], "echo audio/wav"), - (["echo \\%t", "audio/*", "foo.txt"], "echo %t"), - (["echo foo", "audio/*", "foo.txt", plist], "echo foo"), - (["echo %{total}", "audio/*", "foo.txt", plist], "echo 3") -@@ -207,7 +208,10 @@ def test_findmatch(self): - ('"An audio fragment"', audio_basic_entry)), - ([c, "audio/*"], - {"filename": fname}, -- ("/usr/local/bin/showaudio audio/*", audio_entry)), -+ (None, None)), -+ ([c, "audio/wav"], -+ {"filename": fname}, -+ ("/usr/local/bin/showaudio audio/wav", audio_entry)), - ([c, "message/external-body"], - {"plist": plist}, - ("showexternal /dev/null default john python.org /tmp foo bar", message_entry)) -diff --git a/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst b/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst -new file mode 100644 -index 0000000000..da81a1f699 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2022-04-27-18-25-30.gh-issue-68966.gjS8zs.rst -@@ -0,0 +1,4 @@ -+The deprecated mailcap module now refuses to inject unsafe text (filenames, -+MIME types, parameters) into shell commands. Instead of using such text, it -+will warn and act as if a match was not found (or for test commands, as if -+the test failed). diff --git a/python3.10.spec b/python3.10.spec index 40297fd..53634e7 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -13,7 +13,7 @@ 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}.7 +%global general_version %{pybasever}.8 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} @@ -322,16 +322,6 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00382 # 9e275dcdf3934b827994ecc3247d583d5bab7985 -# CVE-2015-20107 -# -# Make mailcap refuse to match unsafe filenames/types/params (GH-91993) -# -# Upstream: https://github.com/python/cpython/issues/68966 -# -# Tracker bug: https://bugzilla.redhat.com/show_bug.cgi?id=2075390 -Patch382: 00382-cve-2015-20107.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1589,6 +1579,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Oct 12 2022 Miro Hrončok - 3.10.8-1 +- Update to 3.10.8 + * Wed Sep 07 2022 Miro Hrončok - 3.10.7-1 - Update to 3.10.7 - Contains security fix for CVE-2020-10735 diff --git a/sources b/sources index 9efa146..f04c9ab 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.7.tar.xz) = dc3432d72ee7382617318c9645204876d13bb61d4caf3fbbb65e6b14897261123c743049657c95e159e5566daf4dcde613d2e393f025de758f610b44eb958313 -SHA512 (Python-3.10.7.tar.xz.asc) = a65d152d87870de763de3384a1c0ff0309068a2af0fcdfa39a6f968a52b59c56229553cf6a955ec0af1d3db5bf4641c4e91d6150764548d2e9fb0e9a01ab759d +SHA512 (Python-3.10.8.tar.xz) = 40e3e77d79618c81d6fc57c5d119b99c2959dcf932f40aad6b26f2ec39c5e713e6ff298f7597b4fad2ab94680db3732483b5ca0a45e6ae58c14580b3ea44cb0f +SHA512 (Python-3.10.8.tar.xz.asc) = 0c2ef09d898257ba5e9ec7c5bb224a7e50e5ebca96843b4d9e25be6cdd2f17144772aafc92280af20c21491e3c8cedc697414688ece613c93b28ff7ecddcf93f From b13d6004fe84e7f5f7b4959a254485c22e86867b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 23 Aug 2022 15:12:53 +0000 Subject: [PATCH 052/112] Update rpmlintrc to rpmlint 2 - Rename to rpmlint.toml - Change from Python function calls to TOML list - Remove rpmlint 1.1 workarounds - Add rpmlint 2.2 workarounds - Adjusts some filters to match rpmlint 2.2 messages Backported from https://src.fedoraproject.org/rpms/python3.11/c/252afb8c115e3ecd34985fcb7e09d8831844584e --- python3.10.rpmlintrc | 95 -------------------------------------------- rpmlint.toml | 88 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 95 deletions(-) delete mode 100644 python3.10.rpmlintrc create mode 100644 rpmlint.toml diff --git a/python3.10.rpmlintrc b/python3.10.rpmlintrc deleted file mode 100644 index 5fc9c03..0000000 --- a/python3.10.rpmlintrc +++ /dev/null @@ -1,95 +0,0 @@ -# KNOWN BUGS: -# https://bugzilla.redhat.com/show_bug.cgi?id=1489816 -addFilter(r'crypto-policy-non-compliance-openssl') - - -# TESTS: -addFilter(r'(zero-length|pem-certificate|uncompressed-zip) /usr/lib(64)?/python3\.\d+/test') - - -# OTHER DELIBERATES: -# chroot function -addFilter(r'missing-call-to-chdir-with-chroot') - -# intentionally unversioned and selfobsoleted -addFilter(r'unversioned-explicit-obsoletes python') -addFilter(r'unversioned Obsoletes: Obsoletes: python3\.\d+$') -addFilter(r'self-obsoletion python3\.\d+ obsoletes python3\.\d+') - -# intentionally hardcoded -addFilter(r'hardcoded-library-path in %{_prefix}/lib/(debug/%{_libdir}|python%{pybasever})') - -# we have non binary stuff, python files -addFilter(r'only-non-binary-in-usr-lib') - -# some devel files that are deliberately needed -addFilter(r'devel-file-in-non-devel-package /usr/include/python3\.\d+m?/pyconfig-(32|64)\.h') -addFilter(r'devel-file-in-non-devel-package /usr/lib(64)?/python3\.\d+/distutils/tests/xxmodule\.c') - -# some bytecode is shipped without sources on purpose, as a space optimization -# if this regex needs to be relaxed in the future, make sure it **does not** match pyc files in __pycache__ -addFilter(r'python-bytecode-without-source /usr/lib(64)?/python3\.\d+/(encodings|pydoc_data)/[^/]+.pyc') - -# SORRY, NOT SORRY: -# manual pages -addFilter(r'no-manual-page-for-binary (idle|pydoc|pyvenv|2to3|python3?-debug|pathfix|msgfmt|pygettext)') -addFilter(r'no-manual-page-for-binary python3?.*-config$') -addFilter(r'no-manual-page-for-binary python3\.\d+dm?$') - -# missing documentation from subpackages -addFilter(r'^python3(\.\d+)?-(debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation') - -# platform python is obsoleted, but not provided -addFilter(r'obsolete-not-provided platform-python') - -# we have extra tokens at the end of %endif/%else directives, we consider them useful -addFilter(r'extra tokens at the end of %(endif|else) directive') - - -# RPMLINT IMPERFECTIONS -# https://github.com/rpm-software-management/rpmlint/issues/123 -addFilter(r'python-bytecode-wrong-magic-value .* expected 33\d\d \(3\.7\), found 3393') -# https://github.com/rpm-software-management/rpmlint/pull/133 -addFilter(r'python-bytecode-wrong-magic-value .* expected 33\d\d \(3\.7\), found 3394') - -# https://bugzilla.redhat.com/show_bug.cgi?id=1550562 -# https://github.com/rpm-software-management/rpmlint/issues/128 -addFilter(r'python-bytecode-inconsistent-mtime .* 1970') - -# we provide python(abi) manually to be sure. createrepo will merge this with the automatic -addFilter(r'python3(\.\d+)?\.[^:-]+: (E|W): useless-provides python\(abi\)') - -# debugsource -addFilter(r'^python3(\.\d+)?-debugsource\.[^:]+: (E|W): no-documentation') - -# debuginfo -addFilter(r'^python3(\.\d+)?-debuginfo\.[^:]+: (E|W): useless-provides debuginfo\(build-id\)') - -# this is OK for F28+ -addFilter(r'library-without-ldconfig-post') - -# debug package contains devel and non-devel files -addFilter(r'python3(\.\d+)?-debug\.[^:]+: (E|W): (non-)?devel-file-in-(non-)?devel-package') - -# this goes to other subpackage, hence not actually dangling, the read error is bogus -addFilter(r'dangling-relative-symlink /usr/lib(64)?/pkgconfig/python-3\.\d+dm?(-embed)?\.pc python-3\.\d+(-embed)?\.pc') -addFilter(r'read-error /usr/lib(64)?/pkgconfig/python-3\.\d+dm?(-embed)?\.pc \[Errno 2\]') - -# the python-unversioned-command package contains dangling symlinks by design -addFilter(r'^python-unversioned-command\.[^:]+: (E|W): dangling-relative-symlink ' - r'(/usr/bin/python \./python3|/usr/share/man/man1/python\.1\S* ./python3\.1\S*)$') - -# we need this macro to evaluate, even if the line starts with # -addFilter(r'macro-in-comment %\{_pyconfig(32|64)_h\}') - -# Python modules don't need to be linked against libc -# Since 3.8 they are no longer linked against libpython3.8.so.1.0 -addFilter(r'(E|W): library-not-linked-against-libc /usr/lib(64)?/python3\.\d+/lib-dynload/') -addFilter(r'(E|W): shared-lib-without-dependency-information /usr/lib(64)?/python3\.\d+/lib-dynload/') - -# specfile-errors are listed twice, once with reason and once without -# we filter out the empty ones -addFilter(r'\bpython3(\.\d+)?\.(src|spec): (E|W): specfile-error\s+$') - -# SPELLING ERRORS -addFilter(r'spelling-error .* en_US (bytecode|pyc|filename|tkinter|namespaces|pytest) ') diff --git a/rpmlint.toml b/rpmlint.toml new file mode 100644 index 0000000..b0b30a6 --- /dev/null +++ b/rpmlint.toml @@ -0,0 +1,88 @@ +Filters = [ + + # KNOWN BUGS: + # https://bugzilla.redhat.com/show_bug.cgi?id=1489816 + 'crypto-policy-non-compliance-openssl', + + + # TESTS: + '(zero-length|pem-certificate|uncompressed-zip) /usr/lib(64)?/python3\.\d+/test', + + + # OTHER DELIBERATES: + # chroot function + 'missing-call-to-chdir-with-chroot', + + # intentionally unversioned and selfobsoleted + 'unversioned-explicit-obsoletes python', + 'unversioned Obsoletes: Obsoletes: python3\.\d+$', + 'self-obsoletion python3\.\d+(-\S+)? obsoletes python3\.\d+(-\S+)?', + + # intentionally hardcoded + 'hardcoded-library-path in %{_prefix}/lib/(debug/%{_libdir}|python%{pybasever})', + + # we have non binary stuff, python files + 'only-non-binary-in-usr-lib', + + # some devel files that are deliberately needed + 'devel-file-in-non-devel-package /usr/include/python3\.\d+m?/pyconfig-(32|64)\.h', + 'devel-file-in-non-devel-package /usr/lib(64)?/python3\.\d+/distutils/tests/xxmodule\.c', + + # some bytecode is shipped without sources on purpose, as a space optimization + # if this regex needs to be relaxed in the future, make sure it **does not** match pyc files in __pycache__ + 'python-bytecode-without-source /usr/lib(64)?/python3\.\d+/(encodings|pydoc_data)/[^/]+.pyc', + + # SORRY, NOT SORRY: + # manual pages + 'no-manual-page-for-binary (idle|pydoc|pyvenv|2to3|python3?-debug|pathfix|msgfmt|pygettext)', + 'no-manual-page-for-binary python3?.*-config$', + 'no-manual-page-for-binary python3\.\d+dm?$', + + # missing documentation from subpackages + '^python3(\.\d+)?-(debug|tkinter|test|idle)\.[^:]+: (E|W): no-documentation', + + # platform python is obsoleted, but not provided + 'obsolete-not-provided platform-python', + + # we have extra tokens at the end of %endif/%else directives, we consider them useful + 'extra tokens at the end of %(endif|else) directive', + + + # RPMLINT IMPERFECTIONS + # https://github.com/rpm-software-management/rpmlint/issues/780 + '/usr/lib/debug', + + # we provide python(abi) manually to be sure. createrepo will merge this with the automatic + 'python3(\.\d+)?\.[^:-]+: (E|W): useless-provides python\(abi\)', + + # debugsource and debuginfo have no docs + '^python3(\.\d+)?-debug(source|info)\.[^:]+: (E|W): no-documentation', + + # this is OK for F28+ + 'library-without-ldconfig-post', + + # debug package contains devel and non-devel files + 'python3(\.\d+)?-debug\.[^:]+: (E|W): (non-)?devel-file-in-(non-)?devel-package', + + # this goes to other subpackage, hence not actually dangling + 'dangling-relative-symlink /usr/lib(64)?/pkgconfig/python-3\.\d+dm?(-embed)?\.pc python-3\.\d+(-embed)?\.pc', + + # the python-unversioned-command package contains dangling symlinks by design + '^python-unversioned-command\.[^:]+: (E|W): dangling-relative-symlink (/usr/bin/python \./python3|/usr/share/man/man1/python\.1\S* ./python3\.1\S*)$', + + # we need this macro to evaluate, even if the line starts with # + 'macro-in-comment %\{_pyconfig(32|64)_h\}', + + # Python modules don't need to be linked against libc + # Since 3.8 they are no longer linked against libpython3.8.so.1.0 + '(E|W): library-not-linked-against-libc /usr/lib(64)?/python3\.\d+/lib-dynload/', + '(E|W): shared-lib(rary)?-without-dependency-information /usr/lib(64)?/python3\.\d+/lib-dynload/', + + # specfile-errors are listed twice, once with reason and once without + # we filter out the empty ones + '\bpython3(\.\d+)?\.(src|spec): (E|W): specfile-error\s+$', + + # SPELLING ERRORS + 'spelling-error .* en_US (bytecode|pyc|filename|tkinter|namespaces|pytest) ', + +] From aa19b39b5d11e943bb5beae21dba0da1ae236880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 23 Aug 2022 15:12:53 +0000 Subject: [PATCH 053/112] Add more rpmlint rules to avoid all reports we see and don't care about Backported from https://src.fedoraproject.org/rpms/python3.11/c/a71ba977876be314fc59759bce0f9f7eaea55af3 Backported from https://src.fedoraproject.org/rpms/python3.11/c/0c6709aa1336854a7225749f4e74c0c868e63601 --- rpmlint.toml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/rpmlint.toml b/rpmlint.toml index b0b30a6..b532441 100644 --- a/rpmlint.toml +++ b/rpmlint.toml @@ -13,6 +13,9 @@ Filters = [ # chroot function 'missing-call-to-chdir-with-chroot', + # gethostbyname function calls gethostbyname + '(E|W): binary-or-shlib-calls-gethostbyname /usr/lib(64)?/python3\.\d+/lib-dynload/_socket\.', + # intentionally unversioned and selfobsoleted 'unversioned-explicit-obsoletes python', 'unversioned Obsoletes: Obsoletes: python3\.\d+$', @@ -27,11 +30,24 @@ Filters = [ # some devel files that are deliberately needed 'devel-file-in-non-devel-package /usr/include/python3\.\d+m?/pyconfig-(32|64)\.h', 'devel-file-in-non-devel-package /usr/lib(64)?/python3\.\d+/distutils/tests/xxmodule\.c', + # ...or are used as test data + 'devel-file-in-non-devel-package /usr/lib(64)?/python3\.\d+/test', # some bytecode is shipped without sources on purpose, as a space optimization # if this regex needs to be relaxed in the future, make sure it **does not** match pyc files in __pycache__ 'python-bytecode-without-source /usr/lib(64)?/python3\.\d+/(encodings|pydoc_data)/[^/]+.pyc', + # DUPLICATE FILES + # test data are often duplicated + '(E|W): files-duplicate /usr/lib(64)?/python3\.\d+/(test|__phello__)/', + # duplicated inits or mains are also common + '(E|W): files-duplicate .+__init__\.py.+__init__\.py', + '(E|W): files-duplicate .+__main__\.py.+__main__\.py', + # files in the debugsource package + '(E|W): files-duplicate /usr/src/debug', + # general waste report + '(E|W): files-duplicated-waste', + # SORRY, NOT SORRY: # manual pages 'no-manual-page-for-binary (idle|pydoc|pyvenv|2to3|python3?-debug|pathfix|msgfmt|pygettext)', @@ -65,6 +81,8 @@ Filters = [ 'python3(\.\d+)?-debug\.[^:]+: (E|W): (non-)?devel-file-in-(non-)?devel-package', # this goes to other subpackage, hence not actually dangling + 'dangling-relative-symlink /usr/bin/python python3', + 'dangling-relative-symlink /usr/share/man/man1/python\.1\.gz python3\.1\.gz', 'dangling-relative-symlink /usr/lib(64)?/pkgconfig/python-3\.\d+dm?(-embed)?\.pc python-3\.\d+(-embed)?\.pc', # the python-unversioned-command package contains dangling symlinks by design From 119d97a7e0c5c5d64131d07e01c89a280b81f0e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 5 Sep 2022 17:32:25 +0000 Subject: [PATCH 054/112] rpminspect: Explicitly list allowed badfuncs in the _socket module See https://github.com/rpminspect/rpminspect/pull/805 Backported from https://src.fedoraproject.org/rpms/python3.11/c/216f3d53bcdd8415503a7541552ca566e097ae07 --- rpminspect.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rpminspect.yaml b/rpminspect.yaml index a111efb..83dfb5e 100644 --- a/rpminspect.yaml +++ b/rpminspect.yaml @@ -6,8 +6,10 @@ xml: # exclude _socket from ipv4 only functions check, it has both ipv4 and ipv6 only badfuncs: - ignore: - - /usr/lib*/python*/lib-dynload/_socket.* + allowed: + /usr/lib*/python*/lib-dynload/_socket.*: + - inet_aton + - inet_ntoa # exclude the debug build from annocheck entirely annocheck: From 49411c201e1a44385b6ee322fae53e8c1bcbc1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 13 Sep 2022 11:30:06 +0000 Subject: [PATCH 055/112] Update the license tag to SPDX See https://gitlab.com/fedora/legal/fedora-license-data/-/merge_requests/61 The LICENSE file differs from the text at https://spdx.org/licenses/Python-2.0.1.html only by: - not saying "Python 2.0.1" but "Python" which is considered OK - copyright years which is considered OK - formatting - listing the history and license for code examples from the documentation (the documentation is not shipped via this package) Backported from https://src.fedoraproject.org/rpms/python3.11/c/2d800732862d491c7f7c355c86d86467c249b1ae --- python3.10.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 53634e7..89496bd 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -18,7 +18,7 @@ URL: https://www.python.org/ %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} Release: 1%{?dist} -License: Python +License: Python-2.0.1 # ================================== From 924c3ebdb17f9fc031c525efb91cd1dab89468c7 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 9 Nov 2022 12:05:00 +0100 Subject: [PATCH 056/112] Fix CVE-2022-42919 --- ...abstract-sockets-for-multiprocessing.patch | 66 +++++++++++++++++++ python3.10.spec | 26 +++++++- 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch diff --git a/00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch b/00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch new file mode 100644 index 0000000..fb7dbad --- /dev/null +++ b/00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Thu, 20 Oct 2022 16:55:51 -0700 +Subject: [PATCH] 00391: Don't use Linux abstract sockets for multiprocessing + +Linux abstract sockets are insecure as they lack any form of filesystem +permissions so their use allows anyone on the system to inject code into +the process. + +This removes the default preference for abstract sockets in +multiprocessing introduced in Python 3.9+ via +https://github.com/python/cpython/pull/18866 while fixing +https://github.com/python/cpython/issues/84031. + +Explicit use of an abstract socket by a user now generates a +RuntimeWarning. If we choose to keep this warning, it should be +backported to the 3.7 and 3.8 branches. +(cherry picked from commit 49f61068f49747164988ffc5a442d2a63874fc17) + +Co-authored-by: Gregory P. Smith + +Automerge-Triggered-By: GH:gpshead +--- + Lib/multiprocessing/connection.py | 5 ----- + .../2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst | 15 +++++++++++++++ + 2 files changed, 15 insertions(+), 5 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst + +diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py +index 510e4b5aba..8e2facf92a 100644 +--- a/Lib/multiprocessing/connection.py ++++ b/Lib/multiprocessing/connection.py +@@ -73,11 +73,6 @@ def arbitrary_address(family): + if family == 'AF_INET': + return ('localhost', 0) + elif family == 'AF_UNIX': +- # Prefer abstract sockets if possible to avoid problems with the address +- # size. When coding portable applications, some implementations have +- # sun_path as short as 92 bytes in the sockaddr_un struct. +- if util.abstract_sockets_supported: +- return f"\0listener-{os.getpid()}-{next(_mmap_counter)}" + return tempfile.mktemp(prefix='listener-', dir=util.get_temp_dir()) + elif family == 'AF_PIPE': + return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' % +diff --git a/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst b/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst +new file mode 100644 +index 0000000000..02d95b5705 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst +@@ -0,0 +1,15 @@ ++On Linux the :mod:`multiprocessing` module returns to using filesystem backed ++unix domain sockets for communication with the *forkserver* process instead of ++the Linux abstract socket namespace. Only code that chooses to use the ++:ref:`"forkserver" start method ` is affected. ++ ++Abstract sockets have no permissions and could allow any user on the system in ++the same `network namespace ++`_ (often the ++whole system) to inject code into the multiprocessing *forkserver* process. ++This was a potential privilege escalation. Filesystem based socket permissions ++restrict this to the *forkserver* process user as was the default in Python 3.8 ++and earlier. ++ ++This prevents Linux `CVE-2022-42919 ++`_. diff --git a/python3.10.spec b/python3.10.spec index 89496bd..8c1f464 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -322,6 +322,26 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00391 # e6d12d8fca6afad3a56dc076c220f213b723a28e +# Don't use Linux abstract sockets for multiprocessing +# +# Linux abstract sockets are insecure as they lack any form of filesystem +# permissions so their use allows anyone on the system to inject code into +# the process. +# +# This removes the default preference for abstract sockets in +# multiprocessing introduced in Python 3.9+ via +# https://github.com/python/cpython/pull/18866 while fixing +# https://github.com/python/cpython/issues/84031. +# +# Explicit use of an abstract socket by a user now generates a +# RuntimeWarning. If we choose to keep this warning, it should be +# backported to the 3.7 and 3.8 branches. +# +# +# Automerge-Triggered-By: GH:gpshead +Patch391: 00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1579,6 +1599,10 @@ CheckPython optimized # ====================================================== %changelog +* Wed Nov 09 2022 Lumír Balhar - 3.10.8-2 +- Fix CVE-2022-42919 +Resolves: rhbz#2138709 + * Wed Oct 12 2022 Miro Hrončok - 3.10.8-1 - Update to 3.10.8 From b399bc200e78cf83644efe7cca1bee1d461bf535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 14 Nov 2022 16:23:15 +0100 Subject: [PATCH 057/112] Make IDLE work without python3-test installed --- 00393-idle---fix-buggy-macosx-patch.patch | 111 ++++++++++++++++++++++ python3.10.spec | 15 ++- 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 00393-idle---fix-buggy-macosx-patch.patch diff --git a/00393-idle---fix-buggy-macosx-patch.patch b/00393-idle---fix-buggy-macosx-patch.patch new file mode 100644 index 0000000..5bb80dc --- /dev/null +++ b/00393-idle---fix-buggy-macosx-patch.patch @@ -0,0 +1,111 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Sun, 16 Oct 2022 08:33:33 -0700 +Subject: [PATCH] 00393: IDLE - fix buggy macosx patch + +GH-97530 fixed IDLE tests possibly crashing on a Mac without a GUI. +But it resulted in IDLE not starting in 3.10.8, 3.12.0a1, and +Microsoft Python 3.10.2288.0 when test/* is not installed. +After this patch, test.* is only imported when testing on Mac. +(cherry picked from commit 35fa5d5e7f2b0971b39b2659dc70cb77e34a7dd6) + +Co-authored-by: Terry Jan Reedy +--- + Lib/idlelib/NEWS.txt | 5 +++ + Lib/idlelib/macosx.py | 42 ++++++++++++------- + ...2-10-15-21-20-40.gh-issue-97527.otAHJM.rst | 3 ++ + 3 files changed, 34 insertions(+), 16 deletions(-) + create mode 100644 Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst + +diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt +index 277fd9429a..521b1f12f9 100644 +--- a/Lib/idlelib/NEWS.txt ++++ b/Lib/idlelib/NEWS.txt +@@ -4,6 +4,11 @@ Released 2023-04-03? + ========================= + + ++gh-97527: Fix a bug in the previous bugfix that caused IDLE to not ++start when run with 3.10.8, 3.12.0a1, and at least Microsoft Python ++3.10.2288.0 installed without the Lib/test package. 3.11.0 was never ++affected. ++ + gh-65802: Document handling of extensions in Save As dialogs. + + gh-95191: Include prompts when saving Shell (interactive input/output). +diff --git a/Lib/idlelib/macosx.py b/Lib/idlelib/macosx.py +index 1085d689f6..f53bd58970 100644 +--- a/Lib/idlelib/macosx.py ++++ b/Lib/idlelib/macosx.py +@@ -4,7 +4,6 @@ + from os.path import expanduser + import plistlib + from sys import platform # Used in _init_tk_type, changed by test. +-from test.support import requires, ResourceDenied + + import tkinter + +@@ -16,27 +15,38 @@ + + def _init_tk_type(): + """ Initialize _tk_type for isXyzTk functions. ++ ++ This function is only called once, when _tk_type is still None. + """ + global _tk_type + if platform == 'darwin': +- try: +- requires('gui') +- except ResourceDenied: # Possible when testing. +- _tk_type = "cocoa" # Newest and most common. +- else: +- root = tkinter.Tk() +- ws = root.tk.call('tk', 'windowingsystem') +- if 'x11' in ws: +- _tk_type = "xquartz" +- elif 'aqua' not in ws: +- _tk_type = "other" +- elif 'AppKit' in root.tk.call('winfo', 'server', '.'): ++ ++ # When running IDLE, GUI is present, test/* may not be. ++ # When running tests, test/* is present, GUI may not be. ++ # If not, guess most common. Does not matter for testing. ++ from idlelib.__init__ import testing ++ if testing: ++ from test.support import requires, ResourceDenied ++ try: ++ requires('gui') ++ except ResourceDenied: + _tk_type = "cocoa" +- else: +- _tk_type = "carbon" +- root.destroy() ++ return ++ ++ root = tkinter.Tk() ++ ws = root.tk.call('tk', 'windowingsystem') ++ if 'x11' in ws: ++ _tk_type = "xquartz" ++ elif 'aqua' not in ws: ++ _tk_type = "other" ++ elif 'AppKit' in root.tk.call('winfo', 'server', '.'): ++ _tk_type = "cocoa" ++ else: ++ _tk_type = "carbon" ++ root.destroy() + else: + _tk_type = "other" ++ return + + def isAquaTk(): + """ +diff --git a/Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst b/Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst +new file mode 100644 +index 0000000000..e7fda89741 +--- /dev/null ++++ b/Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst +@@ -0,0 +1,3 @@ ++Fix a bug in the previous bugfix that caused IDLE to not start when run with ++3.10.8, 3.12.0a1, and at least Microsoft Python 3.10.2288.0 installed ++without the Lib/test package. 3.11.0 was never affected. diff --git a/python3.10.spec b/python3.10.spec index 8c1f464..1f0ea58 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -342,6 +342,15 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # Automerge-Triggered-By: GH:gpshead Patch391: 00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch +# 00393 # 353b3ca7b9e0884839cd6dea28c9bafd9f878571 +# IDLE - fix buggy macosx patch +# +# GH-97530 fixed IDLE tests possibly crashing on a Mac without a GUI. +# But it resulted in IDLE not starting in 3.10.8, 3.12.0a1, and +# Microsoft Python 3.10.2288.0 when test/* is not installed. +# After this patch, test.* is only imported when testing on Mac. +Patch393: 00393-idle---fix-buggy-macosx-patch.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1599,6 +1608,10 @@ CheckPython optimized # ====================================================== %changelog +* Mon Nov 14 2022 Miro Hrončok - 3.10.8-3 +- Make IDLE work without python3-test installed +- Fixes rhbz#2142602 + * Wed Nov 09 2022 Lumír Balhar - 3.10.8-2 - Fix CVE-2022-42919 Resolves: rhbz#2138709 From 4c508562f05742418002a75c8537ea8c5d79274b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Wed, 7 Dec 2022 11:28:27 +0100 Subject: [PATCH 058/112] Update to 3.10.9 --- ...abstract-sockets-for-multiprocessing.patch | 66 ----------- 00393-idle---fix-buggy-macosx-patch.patch | 111 ------------------ python3.10.spec | 40 ++----- sources | 4 +- 4 files changed, 9 insertions(+), 212 deletions(-) delete mode 100644 00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch delete mode 100644 00393-idle---fix-buggy-macosx-patch.patch diff --git a/00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch b/00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch deleted file mode 100644 index fb7dbad..0000000 --- a/00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Miss Islington (bot)" - <31488909+miss-islington@users.noreply.github.com> -Date: Thu, 20 Oct 2022 16:55:51 -0700 -Subject: [PATCH] 00391: Don't use Linux abstract sockets for multiprocessing - -Linux abstract sockets are insecure as they lack any form of filesystem -permissions so their use allows anyone on the system to inject code into -the process. - -This removes the default preference for abstract sockets in -multiprocessing introduced in Python 3.9+ via -https://github.com/python/cpython/pull/18866 while fixing -https://github.com/python/cpython/issues/84031. - -Explicit use of an abstract socket by a user now generates a -RuntimeWarning. If we choose to keep this warning, it should be -backported to the 3.7 and 3.8 branches. -(cherry picked from commit 49f61068f49747164988ffc5a442d2a63874fc17) - -Co-authored-by: Gregory P. Smith - -Automerge-Triggered-By: GH:gpshead ---- - Lib/multiprocessing/connection.py | 5 ----- - .../2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst | 15 +++++++++++++++ - 2 files changed, 15 insertions(+), 5 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst - -diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py -index 510e4b5aba..8e2facf92a 100644 ---- a/Lib/multiprocessing/connection.py -+++ b/Lib/multiprocessing/connection.py -@@ -73,11 +73,6 @@ def arbitrary_address(family): - if family == 'AF_INET': - return ('localhost', 0) - elif family == 'AF_UNIX': -- # Prefer abstract sockets if possible to avoid problems with the address -- # size. When coding portable applications, some implementations have -- # sun_path as short as 92 bytes in the sockaddr_un struct. -- if util.abstract_sockets_supported: -- return f"\0listener-{os.getpid()}-{next(_mmap_counter)}" - return tempfile.mktemp(prefix='listener-', dir=util.get_temp_dir()) - elif family == 'AF_PIPE': - return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' % -diff --git a/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst b/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst -new file mode 100644 -index 0000000000..02d95b5705 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2022-09-07-10-42-00.gh-issue-97514.Yggdsl.rst -@@ -0,0 +1,15 @@ -+On Linux the :mod:`multiprocessing` module returns to using filesystem backed -+unix domain sockets for communication with the *forkserver* process instead of -+the Linux abstract socket namespace. Only code that chooses to use the -+:ref:`"forkserver" start method ` is affected. -+ -+Abstract sockets have no permissions and could allow any user on the system in -+the same `network namespace -+`_ (often the -+whole system) to inject code into the multiprocessing *forkserver* process. -+This was a potential privilege escalation. Filesystem based socket permissions -+restrict this to the *forkserver* process user as was the default in Python 3.8 -+and earlier. -+ -+This prevents Linux `CVE-2022-42919 -+`_. diff --git a/00393-idle---fix-buggy-macosx-patch.patch b/00393-idle---fix-buggy-macosx-patch.patch deleted file mode 100644 index 5bb80dc..0000000 --- a/00393-idle---fix-buggy-macosx-patch.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Miss Islington (bot)" - <31488909+miss-islington@users.noreply.github.com> -Date: Sun, 16 Oct 2022 08:33:33 -0700 -Subject: [PATCH] 00393: IDLE - fix buggy macosx patch - -GH-97530 fixed IDLE tests possibly crashing on a Mac without a GUI. -But it resulted in IDLE not starting in 3.10.8, 3.12.0a1, and -Microsoft Python 3.10.2288.0 when test/* is not installed. -After this patch, test.* is only imported when testing on Mac. -(cherry picked from commit 35fa5d5e7f2b0971b39b2659dc70cb77e34a7dd6) - -Co-authored-by: Terry Jan Reedy ---- - Lib/idlelib/NEWS.txt | 5 +++ - Lib/idlelib/macosx.py | 42 ++++++++++++------- - ...2-10-15-21-20-40.gh-issue-97527.otAHJM.rst | 3 ++ - 3 files changed, 34 insertions(+), 16 deletions(-) - create mode 100644 Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst - -diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt -index 277fd9429a..521b1f12f9 100644 ---- a/Lib/idlelib/NEWS.txt -+++ b/Lib/idlelib/NEWS.txt -@@ -4,6 +4,11 @@ Released 2023-04-03? - ========================= - - -+gh-97527: Fix a bug in the previous bugfix that caused IDLE to not -+start when run with 3.10.8, 3.12.0a1, and at least Microsoft Python -+3.10.2288.0 installed without the Lib/test package. 3.11.0 was never -+affected. -+ - gh-65802: Document handling of extensions in Save As dialogs. - - gh-95191: Include prompts when saving Shell (interactive input/output). -diff --git a/Lib/idlelib/macosx.py b/Lib/idlelib/macosx.py -index 1085d689f6..f53bd58970 100644 ---- a/Lib/idlelib/macosx.py -+++ b/Lib/idlelib/macosx.py -@@ -4,7 +4,6 @@ - from os.path import expanduser - import plistlib - from sys import platform # Used in _init_tk_type, changed by test. --from test.support import requires, ResourceDenied - - import tkinter - -@@ -16,27 +15,38 @@ - - def _init_tk_type(): - """ Initialize _tk_type for isXyzTk functions. -+ -+ This function is only called once, when _tk_type is still None. - """ - global _tk_type - if platform == 'darwin': -- try: -- requires('gui') -- except ResourceDenied: # Possible when testing. -- _tk_type = "cocoa" # Newest and most common. -- else: -- root = tkinter.Tk() -- ws = root.tk.call('tk', 'windowingsystem') -- if 'x11' in ws: -- _tk_type = "xquartz" -- elif 'aqua' not in ws: -- _tk_type = "other" -- elif 'AppKit' in root.tk.call('winfo', 'server', '.'): -+ -+ # When running IDLE, GUI is present, test/* may not be. -+ # When running tests, test/* is present, GUI may not be. -+ # If not, guess most common. Does not matter for testing. -+ from idlelib.__init__ import testing -+ if testing: -+ from test.support import requires, ResourceDenied -+ try: -+ requires('gui') -+ except ResourceDenied: - _tk_type = "cocoa" -- else: -- _tk_type = "carbon" -- root.destroy() -+ return -+ -+ root = tkinter.Tk() -+ ws = root.tk.call('tk', 'windowingsystem') -+ if 'x11' in ws: -+ _tk_type = "xquartz" -+ elif 'aqua' not in ws: -+ _tk_type = "other" -+ elif 'AppKit' in root.tk.call('winfo', 'server', '.'): -+ _tk_type = "cocoa" -+ else: -+ _tk_type = "carbon" -+ root.destroy() - else: - _tk_type = "other" -+ return - - def isAquaTk(): - """ -diff --git a/Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst b/Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst -new file mode 100644 -index 0000000000..e7fda89741 ---- /dev/null -+++ b/Misc/NEWS.d/next/IDLE/2022-10-15-21-20-40.gh-issue-97527.otAHJM.rst -@@ -0,0 +1,3 @@ -+Fix a bug in the previous bugfix that caused IDLE to not start when run with -+3.10.8, 3.12.0a1, and at least Microsoft Python 3.10.2288.0 installed -+without the Lib/test package. 3.11.0 was never affected. diff --git a/python3.10.spec b/python3.10.spec index 1f0ea58..432eedd 100644 --- a/python3.10.spec +++ b/python3.10.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}.8 +%global general_version %{pybasever}.9 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -67,8 +67,8 @@ License: Python-2.0.1 # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 22.2.2 -%global setuptools_version 63.2.0 +%global pip_version 22.3.1 +%global setuptools_version 65.5.0 # Expensive optimizations (mainly, profile-guided optimizations) %bcond_without optimizations @@ -322,35 +322,6 @@ Patch328: 00328-pyc-timestamp-invalidation-mode.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00391 # e6d12d8fca6afad3a56dc076c220f213b723a28e -# Don't use Linux abstract sockets for multiprocessing -# -# Linux abstract sockets are insecure as they lack any form of filesystem -# permissions so their use allows anyone on the system to inject code into -# the process. -# -# This removes the default preference for abstract sockets in -# multiprocessing introduced in Python 3.9+ via -# https://github.com/python/cpython/pull/18866 while fixing -# https://github.com/python/cpython/issues/84031. -# -# Explicit use of an abstract socket by a user now generates a -# RuntimeWarning. If we choose to keep this warning, it should be -# backported to the 3.7 and 3.8 branches. -# -# -# Automerge-Triggered-By: GH:gpshead -Patch391: 00391-don-t-use-linux-abstract-sockets-for-multiprocessing.patch - -# 00393 # 353b3ca7b9e0884839cd6dea28c9bafd9f878571 -# IDLE - fix buggy macosx patch -# -# GH-97530 fixed IDLE tests possibly crashing on a Mac without a GUI. -# But it resulted in IDLE not starting in 3.10.8, 3.12.0a1, and -# Microsoft Python 3.10.2288.0 when test/* is not installed. -# After this patch, test.* is only imported when testing on Mac. -Patch393: 00393-idle---fix-buggy-macosx-patch.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1608,6 +1579,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Dec 07 2022 Tomáš Hrnčiar - 3.10.9-1 +- Update to 3.10.9 + * Mon Nov 14 2022 Miro Hrončok - 3.10.8-3 - Make IDLE work without python3-test installed - Fixes rhbz#2142602 diff --git a/sources b/sources index f04c9ab..f7775cf 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.8.tar.xz) = 40e3e77d79618c81d6fc57c5d119b99c2959dcf932f40aad6b26f2ec39c5e713e6ff298f7597b4fad2ab94680db3732483b5ca0a45e6ae58c14580b3ea44cb0f -SHA512 (Python-3.10.8.tar.xz.asc) = 0c2ef09d898257ba5e9ec7c5bb224a7e50e5ebca96843b4d9e25be6cdd2f17144772aafc92280af20c21491e3c8cedc697414688ece613c93b28ff7ecddcf93f +SHA512 (Python-3.10.9.tar.xz) = d66ea8adeb6dc4951e612175f8838b3092967ff275b7a3470f2d86f470036aa2221e722c3144d90bcd230b88efd53dde204213f72f703e524e4b833e2ccc68e2 +SHA512 (Python-3.10.9.tar.xz.asc) = 525e166ede6836086de814c26fc880f41eaf1ed4bff6118f00342e42f7ab1c47148447ced1b565e146d3125fa06b5cd6b394a256bc61096766b26e07f18bbf10 From f6a8197f411235a8f754a477f176de2f57a3d90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 20 Dec 2022 20:50:42 +0100 Subject: [PATCH 059/112] Supplement tox from the devel package tox only Recommends python3.10, not python3.10-devel. Since this is the oldest "nonflat" alternate Python version package, this was forgotten. See https://src.fedoraproject.org/rpms/python3.11/c/771f810493740f35e92e75cdd52dd9dd4b5fa621 See also https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/thread/NVVUXSVSPFQOWIGBE2JNI67HEO7R63ZQ/ --- python3.10.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 432eedd..d2ee951 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -498,6 +498,9 @@ Requires: (pyproject-rpm-macros if rpm-build) Recommends: %{pkgname}-pip %endif +# tox users are likely to need the devel subpackage +Supplements: tox + %if %{without bootstrap} Requires: (python3-rpm-generators if rpm-build) %endif @@ -1579,6 +1582,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Dec 20 2022 Miro Hrončok - 3.10.9-2 +- Supplement tox from the devel package + * Wed Dec 07 2022 Tomáš Hrnčiar - 3.10.9-1 - Update to 3.10.9 From 550562473d38af1e41d8a4328477cea9f4661b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 19 Dec 2022 16:21:06 +0000 Subject: [PATCH 060/112] No longer patch the default bytecode cache invalidation policy That is, drop patch 328. Fixes https://bugzilla.redhat.com/2133850 See also https://src.fedoraproject.org/rpms/python-rpm-macros/pull-request/154 This is part of https://fedoraproject.org/wiki/Changes/ReproducibleBuildsClampMtimes --- 00328-pyc-timestamp-invalidation-mode.patch | 54 --------------------- check-pyc-timestamps.py | 8 ++- python3.10.spec | 31 ++++++------ 3 files changed, 18 insertions(+), 75 deletions(-) delete mode 100644 00328-pyc-timestamp-invalidation-mode.patch diff --git a/00328-pyc-timestamp-invalidation-mode.patch b/00328-pyc-timestamp-invalidation-mode.patch deleted file mode 100644 index 26f09f2..0000000 --- a/00328-pyc-timestamp-invalidation-mode.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= -Date: Thu, 11 Jul 2019 13:44:13 +0200 -Subject: [PATCH] 00328: Restore pyc to TIMESTAMP invalidation mode as default - in rpmbuild - -Since Fedora 31, the $SOURCE_DATE_EPOCH is set in rpmbuild to the latest -%changelog date. This makes Python default to the CHECKED_HASH pyc -invalidation mode, bringing more reproducible builds traded for an import -performance decrease. To avoid that, we don't default to CHECKED_HASH -when $RPM_BUILD_ROOT is set (i.e. when we are building RPM packages). - -See https://src.fedoraproject.org/rpms/redhat-rpm-config/pull-request/57#comment-27426 -Downstream only: only used when building RPM packages -Ideally, we should talk to upstream and explain why we don't want this ---- - Lib/py_compile.py | 3 ++- - Lib/test/test_py_compile.py | 2 ++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/Lib/py_compile.py b/Lib/py_compile.py -index 388614e51b..db52725016 100644 ---- a/Lib/py_compile.py -+++ b/Lib/py_compile.py -@@ -70,7 +70,8 @@ class PycInvalidationMode(enum.Enum): - - - def _get_default_invalidation_mode(): -- if os.environ.get('SOURCE_DATE_EPOCH'): -+ if (os.environ.get('SOURCE_DATE_EPOCH') and not -+ os.environ.get('RPM_BUILD_ROOT')): - return PycInvalidationMode.CHECKED_HASH - else: - return PycInvalidationMode.TIMESTAMP -diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py -index 5ed98dbff1..f30c4e43de 100644 ---- a/Lib/test/test_py_compile.py -+++ b/Lib/test/test_py_compile.py -@@ -19,6 +19,7 @@ def without_source_date_epoch(fxn): - def wrapper(*args, **kwargs): - with os_helper.EnvironmentVarGuard() as env: - env.unset('SOURCE_DATE_EPOCH') -+ env.unset('RPM_BUILD_ROOT') - return fxn(*args, **kwargs) - return wrapper - -@@ -29,6 +30,7 @@ def with_source_date_epoch(fxn): - def wrapper(*args, **kwargs): - with os_helper.EnvironmentVarGuard() as env: - env['SOURCE_DATE_EPOCH'] = '123456789' -+ env.unset('RPM_BUILD_ROOT') - return fxn(*args, **kwargs) - return wrapper - diff --git a/check-pyc-timestamps.py b/check-pyc-timestamps.py index 91af4fd..e421fca 100644 --- a/check-pyc-timestamps.py +++ b/check-pyc-timestamps.py @@ -19,11 +19,9 @@ not_compiled = [ '*/test/bad_coding.py', '*/test/bad_coding2.py', '*/test/badsyntax_*.py', - '*/lib2to3/tests/data/bom.py', - '*/lib2to3/tests/data/crlf.py', - '*/lib2to3/tests/data/different_encoding.py', - '*/lib2to3/tests/data/false_encoding.py', - '*/lib2to3/tests/data/py2_test_grammar.py', + '*/lib2to3/tests/data/*.py', + '*/lib2to3/tests/data/*/*.py', + '*/lib2to3/tests/data/*/*/*.py', '*.debug-gdb.py', ] diff --git a/python3.10.spec b/python3.10.spec index d2ee951..46b9d20 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -297,20 +297,6 @@ Patch1: 00001-rpath.patch # pypa/distutils integration: https://github.com/pypa/distutils/pull/70 Patch251: 00251-change-user-install-location.patch -# 00328 # 318e500c98f5e59eb1f23e0fcd32db69b9bd17e1 -# Restore pyc to TIMESTAMP invalidation mode as default in rpmbuild -# -# Since Fedora 31, the $SOURCE_DATE_EPOCH is set in rpmbuild to the latest -# %%changelog date. This makes Python default to the CHECKED_HASH pyc -# invalidation mode, bringing more reproducible builds traded for an import -# performance decrease. To avoid that, we don't default to CHECKED_HASH -# when $RPM_BUILD_ROOT is set (i.e. when we are building RPM packages). -# -# See https://src.fedoraproject.org/rpms/redhat-rpm-config/pull-request/57#comment-27426 -# Downstream only: only used when building RPM packages -# Ideally, we should talk to upstream and explain why we don't want this -Patch328: 00328-pyc-timestamp-invalidation-mode.patch - # 00371 # c1754d9c2750f89cb702e1b63a99201f5f7cff00 # Revert "bpo-1596321: Fix threading._shutdown() for the main thread (GH-28549) (GH-28589)" # @@ -953,15 +939,25 @@ find . -name "*~" -exec rm -f {} \; # Python CMD line options: # -s - don't add user site directory to sys.path # -B - don't write .pyc files on import +# Clamp the source mtime first, see https://fedoraproject.org/wiki/Changes/ReproducibleBuildsClampMtimes +# The clamp_source_mtime module is only guaranteed to exist on Fedoras that enabled this option: +%if 0%{?clamp_mtime_to_source_date_epoch} +LD_LIBRARY_PATH="%{buildroot}%{dynload_dir}/:%{buildroot}%{_libdir}" \ +PYTHONPATH="%{_rpmconfigdir}/redhat" \ +%{buildroot}%{_bindir}/python%{pybasever} -s -B -m clamp_source_mtime %{buildroot}%{pylibdir} +%endif # compileall CMD line options: # -f - force rebuild even if timestamps are up to date # -o - optimization levels to run compilation with # -s - part of path to left-strip from path to source file (buildroot) # -p - path to add as prefix to path to source file (/ to make it absolute) # --hardlink-dupes - hardlink different optimization level pycs together if identical (saves space) +# --invalidation-mode - we prefer the timestamp invalidation mode for performance reasons +# -x - skip test modules with SyntaxErrors (taken from the Makefile) LD_LIBRARY_PATH="%{buildroot}%{dynload_dir}/:%{buildroot}%{_libdir}" \ %{buildroot}%{_bindir}/python%{pybasever} -s -B -m compileall \ --f %{_smp_mflags} -o 0 -o 1 -o 2 -s %{buildroot} -p / %{buildroot} --hardlink-dupes || : +-f %{_smp_mflags} -o 0 -o 1 -o 2 -s %{buildroot} -p / %{buildroot} --hardlink-dupes --invalidation-mode=timestamp \ +-x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' # Turn this BRP off, it is done by compileall2 --hardlink-dupes above %global __brp_python_hardlink %{nil} @@ -1582,6 +1578,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Dec 21 2022 Miro Hrončok - 3.10.9-3 +- No longer patch the default bytecode cache invalidation policy + * Tue Dec 20 2022 Miro Hrončok - 3.10.9-2 - Supplement tox from the devel package From ad089d6d9f4a2196b4755fa58e1f00bc18bc39c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 6 Jan 2023 11:05:28 +0000 Subject: [PATCH 061/112] Opt-out from https://fedoraproject.org/wiki/Changes/fno-omit-frame-pointer See https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/thread/6TQYCHMX4FZLF27U5BCEC7IFV6XNBKJP/ for rationale, namely https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/message/ZVDEXGPU6JQFXB3XHYZ4IXVQNNR3YM3V/ Summary: Python is currently slower with frame pointers due to a slowdown in _PyEval_EvalFrameDefault, but we expect this to be solved in Python 3.12. Tracking bugzilla: https://bugzilla.redhat.com/2158729 This change does not require a release bump. It is only needed to be here to prevent the next builds from including frame pointers. --- python3.10.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index 46b9d20..007de02 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -175,6 +175,12 @@ Obsoletes: python%{pybasever}%{?1:-%{1}}\ %define unversioned_obsoletes_of_python3_X_if_main() %{nil} %endif +# Opt-out from https://fedoraproject.org/wiki/Changes/fno-omit-frame-pointer +# Python is slower with frame pointers, but we expect to remove this in Python 3.12+ +# See https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/thread/6TQYCHMX4FZLF27U5BCEC7IFV6XNBKJP/ +# Tracking bugzilla: https://bugzilla.redhat.com/2158729 +%undefine _include_frame_pointers + # ======================= # Build-time requirements # ======================= From 70c29816959f604b9283d1224f0e1003669761da Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 20 Jan 2023 18:45:00 +0000 Subject: [PATCH 062/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 007de02..d63f6b8 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python-2.0.1 @@ -1584,6 +1584,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jan 20 2023 Fedora Release Engineering - 3.10.9-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + * Wed Dec 21 2022 Miro Hrončok - 3.10.9-3 - No longer patch the default bytecode cache invalidation policy From f7c068e6b95b5ee7e50db54d86b6dca91da98369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Wed, 8 Feb 2023 16:42:47 +0100 Subject: [PATCH 063/112] Update to 3.10.10 --- python3.10.spec | 9 +++++++-- sources | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index d63f6b8..7c75a28 100644 --- a/python3.10.spec +++ b/python3.10.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}.9 +%global general_version %{pybasever}.10 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -1427,6 +1427,7 @@ CheckPython optimized %{dynload_dir}/_ctypes_test.%{SOABI_optimized}.so %{dynload_dir}/_testbuffer.%{SOABI_optimized}.so %{dynload_dir}/_testcapi.%{SOABI_optimized}.so +%{dynload_dir}/_testclinic.%{SOABI_optimized}.so %{dynload_dir}/_testimportmultiple.%{SOABI_optimized}.so %{dynload_dir}/_testinternalcapi.%{SOABI_optimized}.so %{dynload_dir}/_testmultiphase.%{SOABI_optimized}.so @@ -1554,6 +1555,7 @@ CheckPython optimized %{dynload_dir}/_ctypes_test.%{SOABI_debug}.so %{dynload_dir}/_testbuffer.%{SOABI_debug}.so %{dynload_dir}/_testcapi.%{SOABI_debug}.so +%{dynload_dir}/_testclinic.%{SOABI_debug}.so %{dynload_dir}/_testimportmultiple.%{SOABI_debug}.so %{dynload_dir}/_testinternalcapi.%{SOABI_debug}.so %{dynload_dir}/_testmultiphase.%{SOABI_debug}.so @@ -1584,6 +1586,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Feb 08 2023 Tomáš Hrnčiar - 3.10.10-1 +- Update to 3.10.10 + * Fri Jan 20 2023 Fedora Release Engineering - 3.10.9-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild diff --git a/sources b/sources index f7775cf..ee15d48 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.9.tar.xz) = d66ea8adeb6dc4951e612175f8838b3092967ff275b7a3470f2d86f470036aa2221e722c3144d90bcd230b88efd53dde204213f72f703e524e4b833e2ccc68e2 -SHA512 (Python-3.10.9.tar.xz.asc) = 525e166ede6836086de814c26fc880f41eaf1ed4bff6118f00342e42f7ab1c47148447ced1b565e146d3125fa06b5cd6b394a256bc61096766b26e07f18bbf10 +SHA512 (Python-3.10.10.tar.xz) = f0aee65970a68287b34c4eafcf35c6fa09c81ba234ac356db16fbbc6c36417e4ac67071e616d118f5e192d541d7f177dcab5585b9780e842f656c09e01c37ced +SHA512 (Python-3.10.10.tar.xz.asc) = 591746d74c6123bf36c763b6e8e1de1554f02eeff30c855623ef0f12d3864d5573eb5efe96d6e142f24627c77b90738ada3456df4ad59bddcb008658f2ca8af9 From 1797d6370092f58c49282274e8257faf0e919249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Wed, 5 Apr 2023 14:36:49 +0200 Subject: [PATCH 064/112] Update to 3.10.11 --- python3.10.spec | 7 +++++-- sources | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 7c75a28..e1f4bdb 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -13,7 +13,7 @@ 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}.10 +%global general_version %{pybasever}.11 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} @@ -67,7 +67,7 @@ License: Python-2.0.1 # If the rpmwheels condition is disabled, we use the bundled wheel packages # from Python with the versions below. # This needs to be manually updated when we update Python. -%global pip_version 22.3.1 +%global pip_version 23.0.1 %global setuptools_version 65.5.0 # Expensive optimizations (mainly, profile-guided optimizations) @@ -1586,6 +1586,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Apr 05 2023 Tomáš Hrnčiar - 3.10.11-1 +- Update to 3.10.11 + * Wed Feb 08 2023 Tomáš Hrnčiar - 3.10.10-1 - Update to 3.10.10 diff --git a/sources b/sources index ee15d48..5418fac 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.10.tar.xz) = f0aee65970a68287b34c4eafcf35c6fa09c81ba234ac356db16fbbc6c36417e4ac67071e616d118f5e192d541d7f177dcab5585b9780e842f656c09e01c37ced -SHA512 (Python-3.10.10.tar.xz.asc) = 591746d74c6123bf36c763b6e8e1de1554f02eeff30c855623ef0f12d3864d5573eb5efe96d6e142f24627c77b90738ada3456df4ad59bddcb008658f2ca8af9 +SHA512 (Python-3.10.11.tar.xz) = fa113b4b635d271a1412999587ec64654d337db263851a6a9d88b3cab4ed66dba76fe03e65c4d341f0a83fd8182d35e245bfd9827465d7aebcb4deb71af4d047 +SHA512 (Python-3.10.11.tar.xz.asc) = edddacc81d4671851cd2a52853cabc53314fa226dac77c2248ee61cf7d58dd2f59301b7729b2ff9f5717b84268140c3bef30e358b80718c6c84b308bd560bcd8 From db3fe4ad656043bd64e7154a6aa0377f20c8e1e1 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Mon, 29 May 2023 17:16:39 +0200 Subject: [PATCH 065/112] Fix for CVE-2023-24329 Resolves: rhbz#2174010 --- 00399-cve-2023-24329.patch | 223 +++++++++++++++++++++++++++++++++++++ python3.10.spec | 18 ++- 2 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 00399-cve-2023-24329.patch diff --git a/00399-cve-2023-24329.patch b/00399-cve-2023-24329.patch new file mode 100644 index 0000000..c94db0a --- /dev/null +++ b/00399-cve-2023-24329.patch @@ -0,0 +1,223 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Wed, 17 May 2023 16:06:06 -0700 +Subject: [PATCH] 00399: CVE-2023-24329 + +gh-102153: Start stripping C0 control and space chars in `urlsplit` (GH-102508) + +`urllib.parse.urlsplit` has already been respecting the WHATWG spec a bit GH-25595. + +This adds more sanitizing to respect the "Remove any leading C0 control or space from input" [rule](https://url.spec.whatwg.org/GH-url-parsing:~:text=Remove%20any%20leading%20and%20trailing%20C0%20control%20or%20space%20from%20input.) in response to [CVE-2023-24329](https://nvd.nist.gov/vuln/detail/CVE-2023-24329). + +--------- + +(cherry picked from commit 2f630e1ce18ad2e07428296532a68b11dc66ad10) +(cherry picked from commit 610cc0ab1b760b2abaac92bd256b96191c46b941) + +Co-authored-by: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> +Co-authored-by: Illia Volochii +Co-authored-by: Gregory P. Smith [Google] +--- + Doc/library/urllib.parse.rst | 38 +++++++++++- + Lib/test/test_urlparse.py | 61 ++++++++++++++++++- + Lib/urllib/parse.py | 12 ++++ + ...-03-07-20-59-17.gh-issue-102153.14CLSZ.rst | 3 + + 4 files changed, 111 insertions(+), 3 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst + +diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst +index 96b3965107..1e85602951 100644 +--- a/Doc/library/urllib.parse.rst ++++ b/Doc/library/urllib.parse.rst +@@ -159,6 +159,10 @@ or on combining URL components into a URL string. + ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', + params='', query='', fragment='') + ++ .. warning:: ++ ++ :func:`urlparse` does not perform validation. See :ref:`URL parsing ++ security ` for details. + + .. versionchanged:: 3.2 + Added IPv6 URL parsing capabilities. +@@ -324,8 +328,14 @@ or on combining URL components into a URL string. + ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is + decomposed before parsing, no error will be raised. + +- Following the `WHATWG spec`_ that updates RFC 3986, ASCII newline +- ``\n``, ``\r`` and tab ``\t`` characters are stripped from the URL. ++ Following some of the `WHATWG spec`_ that updates RFC 3986, leading C0 ++ control and space characters are stripped from the URL. ``\n``, ++ ``\r`` and tab ``\t`` characters are removed from the URL at any position. ++ ++ .. warning:: ++ ++ :func:`urlsplit` does not perform validation. See :ref:`URL parsing ++ security ` for details. + + .. versionchanged:: 3.6 + Out-of-range port numbers now raise :exc:`ValueError`, instead of +@@ -338,6 +348,9 @@ or on combining URL components into a URL string. + .. versionchanged:: 3.10 + ASCII newline and tab characters are stripped from the URL. + ++ .. versionchanged:: 3.10.12 ++ Leading WHATWG C0 control and space characters are stripped from the URL. ++ + .. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser + + .. function:: urlunsplit(parts) +@@ -414,6 +427,27 @@ or on combining URL components into a URL string. + or ``scheme://host/path``). If *url* is not a wrapped URL, it is returned + without changes. + ++.. _url-parsing-security: ++ ++URL parsing security ++-------------------- ++ ++The :func:`urlsplit` and :func:`urlparse` APIs do not perform **validation** of ++inputs. They may not raise errors on inputs that other applications consider ++invalid. They may also succeed on some inputs that might not be considered ++URLs elsewhere. Their purpose is for practical functionality rather than ++purity. ++ ++Instead of raising an exception on unusual input, they may instead return some ++component parts as empty strings. Or components may contain more than perhaps ++they should. ++ ++We recommend that users of these APIs where the values may be used anywhere ++with security implications code defensively. Do some verification within your ++code before trusting a returned component part. Does that ``scheme`` make ++sense? Is that a sensible ``path``? Is there anything strange about that ++``hostname``? etc. ++ + .. _parsing-ascii-encoded-bytes: + + Parsing ASCII Encoded Bytes +diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py +index ca37c3c403..b0aed37de7 100644 +--- a/Lib/test/test_urlparse.py ++++ b/Lib/test/test_urlparse.py +@@ -649,6 +649,65 @@ def test_urlsplit_remove_unsafe_bytes(self): + self.assertEqual(p.scheme, "http") + self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/?query=something#fragment") + ++ def test_urlsplit_strip_url(self): ++ noise = bytes(range(0, 0x20 + 1)) ++ base_url = "http://User:Pass@www.python.org:080/doc/?query=yes#frag" ++ ++ url = noise.decode("utf-8") + base_url ++ p = urllib.parse.urlsplit(url) ++ self.assertEqual(p.scheme, "http") ++ self.assertEqual(p.netloc, "User:Pass@www.python.org:080") ++ self.assertEqual(p.path, "/doc/") ++ self.assertEqual(p.query, "query=yes") ++ self.assertEqual(p.fragment, "frag") ++ self.assertEqual(p.username, "User") ++ self.assertEqual(p.password, "Pass") ++ self.assertEqual(p.hostname, "www.python.org") ++ self.assertEqual(p.port, 80) ++ self.assertEqual(p.geturl(), base_url) ++ ++ url = noise + base_url.encode("utf-8") ++ p = urllib.parse.urlsplit(url) ++ self.assertEqual(p.scheme, b"http") ++ self.assertEqual(p.netloc, b"User:Pass@www.python.org:080") ++ self.assertEqual(p.path, b"/doc/") ++ self.assertEqual(p.query, b"query=yes") ++ self.assertEqual(p.fragment, b"frag") ++ self.assertEqual(p.username, b"User") ++ self.assertEqual(p.password, b"Pass") ++ self.assertEqual(p.hostname, b"www.python.org") ++ self.assertEqual(p.port, 80) ++ self.assertEqual(p.geturl(), base_url.encode("utf-8")) ++ ++ # Test that trailing space is preserved as some applications rely on ++ # this within query strings. ++ query_spaces_url = "https://www.python.org:88/doc/?query= " ++ p = urllib.parse.urlsplit(noise.decode("utf-8") + query_spaces_url) ++ self.assertEqual(p.scheme, "https") ++ self.assertEqual(p.netloc, "www.python.org:88") ++ self.assertEqual(p.path, "/doc/") ++ self.assertEqual(p.query, "query= ") ++ self.assertEqual(p.port, 88) ++ self.assertEqual(p.geturl(), query_spaces_url) ++ ++ p = urllib.parse.urlsplit("www.pypi.org ") ++ # That "hostname" gets considered a "path" due to the ++ # trailing space and our existing logic... YUCK... ++ # and re-assembles via geturl aka unurlsplit into the original. ++ # django.core.validators.URLValidator (at least through v3.2) relies on ++ # this, for better or worse, to catch it in a ValidationError via its ++ # regular expressions. ++ # Here we test the basic round trip concept of such a trailing space. ++ self.assertEqual(urllib.parse.urlunsplit(p), "www.pypi.org ") ++ ++ # with scheme as cache-key ++ url = "//www.python.org/" ++ scheme = noise.decode("utf-8") + "https" + noise.decode("utf-8") ++ for _ in range(2): ++ p = urllib.parse.urlsplit(url, scheme=scheme) ++ self.assertEqual(p.scheme, "https") ++ self.assertEqual(p.geturl(), "https://www.python.org/") ++ + def test_attributes_bad_port(self): + """Check handling of invalid ports.""" + for bytes in (False, True): +@@ -656,7 +715,7 @@ def test_attributes_bad_port(self): + for port in ("foo", "1.5", "-1", "0x10", "-0", "1_1", " 1", "1 ", "६"): + with self.subTest(bytes=bytes, parse=parse, port=port): + netloc = "www.example.net:" + port +- url = "http://" + netloc ++ url = "http://" + netloc + "/" + if bytes: + if netloc.isascii() and port.isascii(): + netloc = netloc.encode("ascii") +diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py +index 26ddf30748..0ab2023843 100644 +--- a/Lib/urllib/parse.py ++++ b/Lib/urllib/parse.py +@@ -25,6 +25,10 @@ + scenarios for parsing, and for backward compatibility purposes, some + parsing quirks from older RFCs are retained. The testcases in + test_urlparse.py provides a good indicator of parsing behavior. ++ ++The WHATWG URL Parser spec should also be considered. We are not compliant with ++it either due to existing user code API behavior expectations (Hyrum's Law). ++It serves as a useful guide when making changes. + """ + + import re +@@ -78,6 +82,10 @@ + '0123456789' + '+-.') + ++# Leading and trailing C0 control and space to be stripped per WHATWG spec. ++# == "".join([chr(i) for i in range(0, 0x20 + 1)]) ++_WHATWG_C0_CONTROL_OR_SPACE = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ' ++ + # Unsafe bytes to be removed per WHATWG spec + _UNSAFE_URL_BYTES_TO_REMOVE = ['\t', '\r', '\n'] + +@@ -455,6 +463,10 @@ def urlsplit(url, scheme='', allow_fragments=True): + """ + + url, scheme, _coerce_result = _coerce_args(url, scheme) ++ # Only lstrip url as some applications rely on preserving trailing space. ++ # (https://url.spec.whatwg.org/#concept-basic-url-parser would strip both) ++ url = url.lstrip(_WHATWG_C0_CONTROL_OR_SPACE) ++ scheme = scheme.strip(_WHATWG_C0_CONTROL_OR_SPACE) + + for b in _UNSAFE_URL_BYTES_TO_REMOVE: + url = url.replace(b, "") +diff --git a/Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst b/Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst +new file mode 100644 +index 0000000000..e57ac4ed3a +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst +@@ -0,0 +1,3 @@ ++:func:`urllib.parse.urlsplit` now strips leading C0 control and space ++characters following the specification for URLs defined by WHATWG in ++response to CVE-2023-24329. Patch by Illia Volochii. diff --git a/python3.10.spec b/python3.10.spec index e1f4bdb..e548823 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -314,6 +314,18 @@ Patch251: 00251-change-user-install-location.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00399 # 9d45c55d8a6f96654b56fba6fbded29745e6fc29 +# CVE-2023-24329 +# +# gh-102153: Start stripping C0 control and space chars in `urlsplit` (GH-102508) +# +# `urllib.parse.urlsplit` has already been respecting the WHATWG spec a bit GH-25595. +# +# This adds more sanitizing to respect the "Remove any leading C0 control or space from input" [rule](https://url.spec.whatwg.org/GH-url-parsing:~:text=Remove%%20any%%20leading%%20and%%20trailing%%20C0%%20control%%20or%%20space%%20from%%20input.) in response to [CVE-2023-24329](https://nvd.nist.gov/vuln/detail/CVE-2023-24329). +# +# --------- +Patch399: 00399-cve-2023-24329.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1586,6 +1598,10 @@ CheckPython optimized # ====================================================== %changelog +* Mon May 29 2023 Charalampos Stratakis - 3.10.11-2 +- Fix for CVE-2023-24329 +Resolves: rhbz#2174010 + * Wed Apr 05 2023 Tomáš Hrnčiar - 3.10.11-1 - Update to 3.10.11 From 718dd7e9a5a304d0d9d8cbe495deaf60a91c8b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Thu, 8 Jun 2023 09:33:27 +0200 Subject: [PATCH 066/112] Update to 3.10.12 --- 00399-cve-2023-24329.patch | 223 ------------------------------------- python3.10.spec | 19 +--- sources | 4 +- 3 files changed, 7 insertions(+), 239 deletions(-) delete mode 100644 00399-cve-2023-24329.patch diff --git a/00399-cve-2023-24329.patch b/00399-cve-2023-24329.patch deleted file mode 100644 index c94db0a..0000000 --- a/00399-cve-2023-24329.patch +++ /dev/null @@ -1,223 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Miss Islington (bot)" - <31488909+miss-islington@users.noreply.github.com> -Date: Wed, 17 May 2023 16:06:06 -0700 -Subject: [PATCH] 00399: CVE-2023-24329 - -gh-102153: Start stripping C0 control and space chars in `urlsplit` (GH-102508) - -`urllib.parse.urlsplit` has already been respecting the WHATWG spec a bit GH-25595. - -This adds more sanitizing to respect the "Remove any leading C0 control or space from input" [rule](https://url.spec.whatwg.org/GH-url-parsing:~:text=Remove%20any%20leading%20and%20trailing%20C0%20control%20or%20space%20from%20input.) in response to [CVE-2023-24329](https://nvd.nist.gov/vuln/detail/CVE-2023-24329). - ---------- - -(cherry picked from commit 2f630e1ce18ad2e07428296532a68b11dc66ad10) -(cherry picked from commit 610cc0ab1b760b2abaac92bd256b96191c46b941) - -Co-authored-by: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> -Co-authored-by: Illia Volochii -Co-authored-by: Gregory P. Smith [Google] ---- - Doc/library/urllib.parse.rst | 38 +++++++++++- - Lib/test/test_urlparse.py | 61 ++++++++++++++++++- - Lib/urllib/parse.py | 12 ++++ - ...-03-07-20-59-17.gh-issue-102153.14CLSZ.rst | 3 + - 4 files changed, 111 insertions(+), 3 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst - -diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst -index 96b3965107..1e85602951 100644 ---- a/Doc/library/urllib.parse.rst -+++ b/Doc/library/urllib.parse.rst -@@ -159,6 +159,10 @@ or on combining URL components into a URL string. - ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html', - params='', query='', fragment='') - -+ .. warning:: -+ -+ :func:`urlparse` does not perform validation. See :ref:`URL parsing -+ security ` for details. - - .. versionchanged:: 3.2 - Added IPv6 URL parsing capabilities. -@@ -324,8 +328,14 @@ or on combining URL components into a URL string. - ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is - decomposed before parsing, no error will be raised. - -- Following the `WHATWG spec`_ that updates RFC 3986, ASCII newline -- ``\n``, ``\r`` and tab ``\t`` characters are stripped from the URL. -+ Following some of the `WHATWG spec`_ that updates RFC 3986, leading C0 -+ control and space characters are stripped from the URL. ``\n``, -+ ``\r`` and tab ``\t`` characters are removed from the URL at any position. -+ -+ .. warning:: -+ -+ :func:`urlsplit` does not perform validation. See :ref:`URL parsing -+ security ` for details. - - .. versionchanged:: 3.6 - Out-of-range port numbers now raise :exc:`ValueError`, instead of -@@ -338,6 +348,9 @@ or on combining URL components into a URL string. - .. versionchanged:: 3.10 - ASCII newline and tab characters are stripped from the URL. - -+ .. versionchanged:: 3.10.12 -+ Leading WHATWG C0 control and space characters are stripped from the URL. -+ - .. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser - - .. function:: urlunsplit(parts) -@@ -414,6 +427,27 @@ or on combining URL components into a URL string. - or ``scheme://host/path``). If *url* is not a wrapped URL, it is returned - without changes. - -+.. _url-parsing-security: -+ -+URL parsing security -+-------------------- -+ -+The :func:`urlsplit` and :func:`urlparse` APIs do not perform **validation** of -+inputs. They may not raise errors on inputs that other applications consider -+invalid. They may also succeed on some inputs that might not be considered -+URLs elsewhere. Their purpose is for practical functionality rather than -+purity. -+ -+Instead of raising an exception on unusual input, they may instead return some -+component parts as empty strings. Or components may contain more than perhaps -+they should. -+ -+We recommend that users of these APIs where the values may be used anywhere -+with security implications code defensively. Do some verification within your -+code before trusting a returned component part. Does that ``scheme`` make -+sense? Is that a sensible ``path``? Is there anything strange about that -+``hostname``? etc. -+ - .. _parsing-ascii-encoded-bytes: - - Parsing ASCII Encoded Bytes -diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py -index ca37c3c403..b0aed37de7 100644 ---- a/Lib/test/test_urlparse.py -+++ b/Lib/test/test_urlparse.py -@@ -649,6 +649,65 @@ def test_urlsplit_remove_unsafe_bytes(self): - self.assertEqual(p.scheme, "http") - self.assertEqual(p.geturl(), "http://www.python.org/javascript:alert('msg')/?query=something#fragment") - -+ def test_urlsplit_strip_url(self): -+ noise = bytes(range(0, 0x20 + 1)) -+ base_url = "http://User:Pass@www.python.org:080/doc/?query=yes#frag" -+ -+ url = noise.decode("utf-8") + base_url -+ p = urllib.parse.urlsplit(url) -+ self.assertEqual(p.scheme, "http") -+ self.assertEqual(p.netloc, "User:Pass@www.python.org:080") -+ self.assertEqual(p.path, "/doc/") -+ self.assertEqual(p.query, "query=yes") -+ self.assertEqual(p.fragment, "frag") -+ self.assertEqual(p.username, "User") -+ self.assertEqual(p.password, "Pass") -+ self.assertEqual(p.hostname, "www.python.org") -+ self.assertEqual(p.port, 80) -+ self.assertEqual(p.geturl(), base_url) -+ -+ url = noise + base_url.encode("utf-8") -+ p = urllib.parse.urlsplit(url) -+ self.assertEqual(p.scheme, b"http") -+ self.assertEqual(p.netloc, b"User:Pass@www.python.org:080") -+ self.assertEqual(p.path, b"/doc/") -+ self.assertEqual(p.query, b"query=yes") -+ self.assertEqual(p.fragment, b"frag") -+ self.assertEqual(p.username, b"User") -+ self.assertEqual(p.password, b"Pass") -+ self.assertEqual(p.hostname, b"www.python.org") -+ self.assertEqual(p.port, 80) -+ self.assertEqual(p.geturl(), base_url.encode("utf-8")) -+ -+ # Test that trailing space is preserved as some applications rely on -+ # this within query strings. -+ query_spaces_url = "https://www.python.org:88/doc/?query= " -+ p = urllib.parse.urlsplit(noise.decode("utf-8") + query_spaces_url) -+ self.assertEqual(p.scheme, "https") -+ self.assertEqual(p.netloc, "www.python.org:88") -+ self.assertEqual(p.path, "/doc/") -+ self.assertEqual(p.query, "query= ") -+ self.assertEqual(p.port, 88) -+ self.assertEqual(p.geturl(), query_spaces_url) -+ -+ p = urllib.parse.urlsplit("www.pypi.org ") -+ # That "hostname" gets considered a "path" due to the -+ # trailing space and our existing logic... YUCK... -+ # and re-assembles via geturl aka unurlsplit into the original. -+ # django.core.validators.URLValidator (at least through v3.2) relies on -+ # this, for better or worse, to catch it in a ValidationError via its -+ # regular expressions. -+ # Here we test the basic round trip concept of such a trailing space. -+ self.assertEqual(urllib.parse.urlunsplit(p), "www.pypi.org ") -+ -+ # with scheme as cache-key -+ url = "//www.python.org/" -+ scheme = noise.decode("utf-8") + "https" + noise.decode("utf-8") -+ for _ in range(2): -+ p = urllib.parse.urlsplit(url, scheme=scheme) -+ self.assertEqual(p.scheme, "https") -+ self.assertEqual(p.geturl(), "https://www.python.org/") -+ - def test_attributes_bad_port(self): - """Check handling of invalid ports.""" - for bytes in (False, True): -@@ -656,7 +715,7 @@ def test_attributes_bad_port(self): - for port in ("foo", "1.5", "-1", "0x10", "-0", "1_1", " 1", "1 ", "६"): - with self.subTest(bytes=bytes, parse=parse, port=port): - netloc = "www.example.net:" + port -- url = "http://" + netloc -+ url = "http://" + netloc + "/" - if bytes: - if netloc.isascii() and port.isascii(): - netloc = netloc.encode("ascii") -diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py -index 26ddf30748..0ab2023843 100644 ---- a/Lib/urllib/parse.py -+++ b/Lib/urllib/parse.py -@@ -25,6 +25,10 @@ - scenarios for parsing, and for backward compatibility purposes, some - parsing quirks from older RFCs are retained. The testcases in - test_urlparse.py provides a good indicator of parsing behavior. -+ -+The WHATWG URL Parser spec should also be considered. We are not compliant with -+it either due to existing user code API behavior expectations (Hyrum's Law). -+It serves as a useful guide when making changes. - """ - - import re -@@ -78,6 +82,10 @@ - '0123456789' - '+-.') - -+# Leading and trailing C0 control and space to be stripped per WHATWG spec. -+# == "".join([chr(i) for i in range(0, 0x20 + 1)]) -+_WHATWG_C0_CONTROL_OR_SPACE = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ' -+ - # Unsafe bytes to be removed per WHATWG spec - _UNSAFE_URL_BYTES_TO_REMOVE = ['\t', '\r', '\n'] - -@@ -455,6 +463,10 @@ def urlsplit(url, scheme='', allow_fragments=True): - """ - - url, scheme, _coerce_result = _coerce_args(url, scheme) -+ # Only lstrip url as some applications rely on preserving trailing space. -+ # (https://url.spec.whatwg.org/#concept-basic-url-parser would strip both) -+ url = url.lstrip(_WHATWG_C0_CONTROL_OR_SPACE) -+ scheme = scheme.strip(_WHATWG_C0_CONTROL_OR_SPACE) - - for b in _UNSAFE_URL_BYTES_TO_REMOVE: - url = url.replace(b, "") -diff --git a/Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst b/Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst -new file mode 100644 -index 0000000000..e57ac4ed3a ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2023-03-07-20-59-17.gh-issue-102153.14CLSZ.rst -@@ -0,0 +1,3 @@ -+:func:`urllib.parse.urlsplit` now strips leading C0 control and space -+characters following the specification for URLs defined by WHATWG in -+response to CVE-2023-24329. Patch by Illia Volochii. diff --git a/python3.10.spec b/python3.10.spec index e548823..196265b 100644 --- a/python3.10.spec +++ b/python3.10.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}.11 +%global general_version %{pybasever}.12 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -314,18 +314,6 @@ Patch251: 00251-change-user-install-location.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00399 # 9d45c55d8a6f96654b56fba6fbded29745e6fc29 -# CVE-2023-24329 -# -# gh-102153: Start stripping C0 control and space chars in `urlsplit` (GH-102508) -# -# `urllib.parse.urlsplit` has already been respecting the WHATWG spec a bit GH-25595. -# -# This adds more sanitizing to respect the "Remove any leading C0 control or space from input" [rule](https://url.spec.whatwg.org/GH-url-parsing:~:text=Remove%%20any%%20leading%%20and%%20trailing%%20C0%%20control%%20or%%20space%%20from%%20input.) in response to [CVE-2023-24329](https://nvd.nist.gov/vuln/detail/CVE-2023-24329). -# -# --------- -Patch399: 00399-cve-2023-24329.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1598,6 +1586,9 @@ CheckPython optimized # ====================================================== %changelog +* Thu Jun 08 2023 Tomáš Hrnčiar - 3.10.12-1 +- Update to 3.10.12 + * Mon May 29 2023 Charalampos Stratakis - 3.10.11-2 - Fix for CVE-2023-24329 Resolves: rhbz#2174010 diff --git a/sources b/sources index 5418fac..cec50a6 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.11.tar.xz) = fa113b4b635d271a1412999587ec64654d337db263851a6a9d88b3cab4ed66dba76fe03e65c4d341f0a83fd8182d35e245bfd9827465d7aebcb4deb71af4d047 -SHA512 (Python-3.10.11.tar.xz.asc) = edddacc81d4671851cd2a52853cabc53314fa226dac77c2248ee61cf7d58dd2f59301b7729b2ff9f5717b84268140c3bef30e358b80718c6c84b308bd560bcd8 +SHA512 (Python-3.10.12.tar.xz) = 5ea018e71bfe7872e02eaf8aef56d5583c0880e4ce5fbbdf8ea76da20c2e94ac6a3ba8badb4b7d1bc21853402a3b63541b04181737417b1626e786b696595cf5 +SHA512 (Python-3.10.12.tar.xz.asc) = d5f1c98d8509e078bf7d7205f9fe25d028178fb7940cff406761c14a2689a82425f6bfe9b58b2aa6e9d4fee53626fb56658e56bd54028245de827dc5ebc1d7d8 From 1a8b07885e88d8a329da3a7afaf44395340fb978 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 21 Jul 2023 15:41:58 +0000 Subject: [PATCH 067/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild Signed-off-by: Fedora Release Engineering --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 196265b..19f0e1f 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -1586,6 +1586,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jul 21 2023 Fedora Release Engineering - 3.10.12-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + * Thu Jun 08 2023 Tomáš Hrnčiar - 3.10.12-1 - Update to 3.10.12 From 53f7dd0a425578094964f1d20d2c61c4d5f99547 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Mon, 22 May 2023 19:23:07 +0200 Subject: [PATCH 068/112] Remove extra distro-applied CFLAGS passed to user-built C extensions Only -fexceptions and -fcf-protection are preserved for binary compatibility with user-built python C extension. https://fedoraproject.org/wiki/Changes/Python_Extension_Flags_Reduction --- python3.10.spec | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 19f0e1f..4a77f6b 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -674,14 +674,15 @@ topdir=$(pwd) # Standard library built here will still use the %%build_...flags, # Fedora packages utilizing %%py3_build will use them as well # https://fedoraproject.org/wiki/Changes/Python_Extension_Flags -export CFLAGS="%{extension_cflags} -D_GNU_SOURCE -fPIC -fwrapv" +# https://fedoraproject.org/wiki/Changes/Python_Extension_Flags_Reduction +export CFLAGS="%{extension_cflags}" export CFLAGS_NODIST="%{build_cflags} -D_GNU_SOURCE -fPIC -fwrapv" -export CXXFLAGS="%{extension_cxxflags} -D_GNU_SOURCE -fPIC -fwrapv" +export CXXFLAGS="%{extension_cxxflags}" export CPPFLAGS="$(pkg-config --cflags-only-I libffi)" -export OPT="%{extension_cflags} -D_GNU_SOURCE -fPIC -fwrapv" +export OPT="%{extension_cflags}" export LINKCC="gcc" export CFLAGS="$CFLAGS $(pkg-config --cflags openssl)" -export LDFLAGS="%{extension_ldflags} -g $(pkg-config --libs-only-L openssl)" +export LDFLAGS="%{extension_ldflags} $(pkg-config --libs-only-L openssl)" export LDFLAGS_NODIST="%{build_ldflags} -g $(pkg-config --libs-only-L openssl)" # We can build several different configurations of Python: regular and debug. @@ -1586,6 +1587,10 @@ CheckPython optimized # ====================================================== %changelog +* Wed Aug 02 2023 Charalampos Stratakis - 3.10.12-3 +- Remove extra distro-applied CFLAGS passed to user built C extensions +- https://fedoraproject.org/wiki/Changes/Python_Extension_Flags_Reduction + * Fri Jul 21 2023 Fedora Release Engineering - 3.10.12-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild From f9e0b9baeacc90c07c38ba7e311d8704def8e555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Mon, 28 Aug 2023 15:35:01 +0200 Subject: [PATCH 069/112] Update to 3.10.13 --- python3.10.spec | 7 +++++-- sources | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 4a77f6b..11b235e 100644 --- a/python3.10.spec +++ b/python3.10.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}.12 +%global general_version %{pybasever}.13 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -1587,6 +1587,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Aug 28 2023 Tomáš Hrnčiar - 3.10.13-1 +- Update to 3.10.13 + * Wed Aug 02 2023 Charalampos Stratakis - 3.10.12-3 - Remove extra distro-applied CFLAGS passed to user built C extensions - https://fedoraproject.org/wiki/Changes/Python_Extension_Flags_Reduction diff --git a/sources b/sources index cec50a6..b4b0734 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.12.tar.xz) = 5ea018e71bfe7872e02eaf8aef56d5583c0880e4ce5fbbdf8ea76da20c2e94ac6a3ba8badb4b7d1bc21853402a3b63541b04181737417b1626e786b696595cf5 -SHA512 (Python-3.10.12.tar.xz.asc) = d5f1c98d8509e078bf7d7205f9fe25d028178fb7940cff406761c14a2689a82425f6bfe9b58b2aa6e9d4fee53626fb56658e56bd54028245de827dc5ebc1d7d8 +SHA512 (Python-3.10.13.tar.xz) = 7579772e501486b2b07f78142082dee1e99c7643640098860ac0cf2ca87daf7588b0c00b1db1960146b37f56a6ed98fd08297c25c9a19b612cf6e6a258984da8 +SHA512 (Python-3.10.13.tar.xz.asc) = 3083e66f8d26128302dc77a0c6ba3bfefc4229928a1bbd06460f2fec2421188bd30d493e3bce138cde1fed1df206e1dda04912b9f43a0b81229f1e69135e3a7f From 034e3e58be9a5246404c09b6c871fc039004ee9f Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Mon, 18 Dec 2023 13:15:37 +0100 Subject: [PATCH 070/112] Security fix for CVE-2023-27043 (rhbz#2196187) --- ...-addresses-in-email-parseaddr-111116.patch | 500 ++++++++++++++++++ python3.10.spec | 14 +- 2 files changed, 513 insertions(+), 1 deletion(-) create mode 100644 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch 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..7d2a813 --- /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 0e266b6a45..6723dc4f13 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 cfdfeb3f1a..9522341fab 100644 +--- a/Lib/email/utils.py ++++ b/Lib/email/utils.py +@@ -48,6 +48,7 @@ + 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): +@@ -205,16 +321,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 8b16cca9bf..5b19bb38f6 100644 +--- a/Lib/test/test_email/test_email.py ++++ b/Lib/test/test_email/test_email.py +@@ -16,6 +16,7 @@ + + import email + import email.policy ++import email.utils + + from email.charset import Charset + from email.generator import Generator, DecodedGenerator, BytesGenerator +@@ -3288,15 +3289,154 @@ def test_getaddresses(self): + [('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""" +@@ -3485,6 +3625,54 @@ def test_mime_classes_policy_argument(self): + 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/python3.10.spec b/python3.10.spec index 11b235e..2d24e03 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -314,6 +314,15 @@ Patch251: 00251-change-user-install-location.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00415 # 9ca4533e0b4a03d919953017026f66c6a060756e +# [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. +Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1587,6 +1596,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Dec 18 2023 Lumír Balhar - 3.10.13-2 +- Security fix for CVE-2023-27043 (rhbz#2196187) + * Mon Aug 28 2023 Tomáš Hrnčiar - 3.10.13-1 - Update to 3.10.13 From 8e56c79b2a43ba1872d8817df29f3b6dfbbf12e9 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Mon, 22 Jan 2024 09:21:36 +0000 Subject: [PATCH 071/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 2d24e03..0f20345 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -1596,6 +1596,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Jan 22 2024 Fedora Release Engineering - 3.10.13-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Mon Dec 18 2023 Lumír Balhar - 3.10.13-2 - Security fix for CVE-2023-27043 (rhbz#2196187) From 740efdfb461ab36d15cea8f4acdc4640967cc199 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 26 Jan 2024 13:31:26 +0000 Subject: [PATCH 072/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 0f20345..39aea88 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python-2.0.1 @@ -1596,6 +1596,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jan 26 2024 Fedora Release Engineering - 3.10.13-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Mon Jan 22 2024 Fedora Release Engineering - 3.10.13-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 433e38e58c506b7ce0fb8d84614731afd7912b86 Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Thu, 25 Jan 2024 13:52:35 +0100 Subject: [PATCH 073/112] Fix test_zlib with zlib-ng-compat --- ...h-non-int-suffix-gh-112771-gh-112774.patch | 66 +++++++++++++++++++ python3.10.spec | 11 +++- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch 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..1e718a6 --- /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 cb0610837b..98cac4fb91 100644 +--- a/Lib/test/test_zlib.py ++++ b/Lib/test/test_zlib.py +@@ -19,6 +19,20 @@ + '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): +@@ -445,9 +459,8 @@ def test_flushes(self): + 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 +@@ -776,16 +789,7 @@ def test_large_unconsumed_tail(self, size): + + 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/python3.10.spec b/python3.10.spec index 39aea88..0a1b1d6 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 5%{?dist} License: Python-2.0.1 @@ -323,6 +323,12 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # Thomas Dwyer. Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch +# 00419 # f13682530cc7e4daec2e40acd56508846fdd3aad +# 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". +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 ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1596,6 +1602,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Jan 29 2024 Karolina Surma - 3.10.13-5 +- Fix test_zlib when building with zlib-ng-compat + * Fri Jan 26 2024 Fedora Release Engineering - 3.10.13-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From f8879650f9b17a9568d6e2d23443bd569c2e78e5 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Wed, 28 Feb 2024 17:08:06 +0100 Subject: [PATCH 074/112] Fix tests for XMLPullParser with Expat 2.6.0 See also: https://bugzilla.redhat.com/2264859 --- ...s-for-xmlpullparser-with-expat-2-6-0.patch | 107 ++++++++++++++++++ python3.10.spec | 12 +- 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch diff --git a/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch b/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch new file mode 100644 index 0000000..a54d321 --- /dev/null +++ b/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Sun, 11 Feb 2024 12:08:39 +0200 +Subject: [PATCH] 00422: gh-115133: Fix tests for XMLPullParser with Expat + 2.6.0 + +Feeding the parser by too small chunks defers parsing to prevent +CVE-2023-52425. Future versions of Expat may be more reactive. + +(cherry picked from commit 4a08e7b3431cd32a0daf22a33421cd3035343dc4) +--- + Lib/test/test_xml_etree.py | 58 ++++++++++++------- + ...-02-08-14-21-28.gh-issue-115133.ycl4ko.rst | 2 + + 2 files changed, 38 insertions(+), 22 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst + +diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py +index 940e02630e..c03d1bacda 100644 +--- a/Lib/test/test_xml_etree.py ++++ b/Lib/test/test_xml_etree.py +@@ -13,6 +13,7 @@ + import operator + import os + import pickle ++import pyexpat + import sys + import textwrap + import types +@@ -120,6 +121,10 @@ + + """ + ++fails_with_expat_2_6_0 = (unittest.expectedFailure ++ if pyexpat.version_info >= (2, 6, 0) else ++ lambda test: test) ++ + def checkwarnings(*filters, quiet=False): + def decorator(test): + def newtest(*args, **kwargs): +@@ -1396,28 +1401,37 @@ def assert_event_tags(self, parser, expected, max_events=None): + self.assertEqual([(action, elem.tag) for action, elem in events], + expected) + +- def test_simple_xml(self): +- for chunk_size in (None, 1, 5): +- with self.subTest(chunk_size=chunk_size): +- parser = ET.XMLPullParser() +- self.assert_event_tags(parser, []) +- self._feed(parser, "\n", chunk_size) +- self.assert_event_tags(parser, []) +- self._feed(parser, +- "\n text\n", chunk_size) +- self.assert_event_tags(parser, [('end', 'element')]) +- self._feed(parser, "texttail\n", chunk_size) +- self._feed(parser, "\n", chunk_size) +- self.assert_event_tags(parser, [ +- ('end', 'element'), +- ('end', 'empty-element'), +- ]) +- self._feed(parser, "\n", chunk_size) +- self.assert_event_tags(parser, [('end', 'root')]) +- self.assertIsNone(parser.close()) ++ def test_simple_xml(self, chunk_size=None): ++ parser = ET.XMLPullParser() ++ self.assert_event_tags(parser, []) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, []) ++ self._feed(parser, ++ "\n text\n", chunk_size) ++ self.assert_event_tags(parser, [('end', 'element')]) ++ self._feed(parser, "texttail\n", chunk_size) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, [ ++ ('end', 'element'), ++ ('end', 'empty-element'), ++ ]) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, [('end', 'root')]) ++ self.assertIsNone(parser.close()) ++ ++ @fails_with_expat_2_6_0 ++ def test_simple_xml_chunk_1(self): ++ self.test_simple_xml(chunk_size=1) ++ ++ @fails_with_expat_2_6_0 ++ def test_simple_xml_chunk_5(self): ++ self.test_simple_xml(chunk_size=5) ++ ++ def test_simple_xml_chunk_22(self): ++ self.test_simple_xml(chunk_size=22) + + def test_feed_while_iterating(self): + parser = ET.XMLPullParser() +diff --git a/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst +new file mode 100644 +index 0000000000..6f1015235c +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst +@@ -0,0 +1,2 @@ ++Fix tests for :class:`~xml.etree.ElementTree.XMLPullParser` with Expat ++2.6.0. diff --git a/python3.10.spec b/python3.10.spec index 0a1b1d6..e4e3677 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 5%{?dist} +Release: 6%{?dist} License: Python-2.0.1 @@ -329,6 +329,13 @@ Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-par # 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 +# 00422 # a353cebef737c41420dc7ae2469dd657371b8881 +# gh-115133: Fix tests for XMLPullParser with Expat 2.6.0 +# +# Feeding the parser by too small chunks defers parsing to prevent +# CVE-2023-52425. Future versions of Expat may be more reactive. +Patch422: 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1602,6 +1609,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Feb 28 2024 Charalampos Stratakis - 3.10.13-6 +- Fix tests for XMLPullParser with Expat 2.6.0 + * Mon Jan 29 2024 Karolina Surma - 3.10.13-5 - Fix test_zlib when building with zlib-ng-compat From d897af59dab6d8a80b26d3ed5a4ec882ee285565 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Wed, 28 Feb 2024 17:08:06 +0100 Subject: [PATCH 075/112] Fix tests for XMLPullParser with Expat 2.6.0 See also: https://bugzilla.redhat.com/2264859 --- ...s-for-xmlpullparser-with-expat-2-6-0.patch | 107 ++++++++++++++++++ python3.10.spec | 12 +- 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch diff --git a/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch b/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch new file mode 100644 index 0000000..a54d321 --- /dev/null +++ b/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch @@ -0,0 +1,107 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Sun, 11 Feb 2024 12:08:39 +0200 +Subject: [PATCH] 00422: gh-115133: Fix tests for XMLPullParser with Expat + 2.6.0 + +Feeding the parser by too small chunks defers parsing to prevent +CVE-2023-52425. Future versions of Expat may be more reactive. + +(cherry picked from commit 4a08e7b3431cd32a0daf22a33421cd3035343dc4) +--- + Lib/test/test_xml_etree.py | 58 ++++++++++++------- + ...-02-08-14-21-28.gh-issue-115133.ycl4ko.rst | 2 + + 2 files changed, 38 insertions(+), 22 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst + +diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py +index 940e02630e..c03d1bacda 100644 +--- a/Lib/test/test_xml_etree.py ++++ b/Lib/test/test_xml_etree.py +@@ -13,6 +13,7 @@ + import operator + import os + import pickle ++import pyexpat + import sys + import textwrap + import types +@@ -120,6 +121,10 @@ + + """ + ++fails_with_expat_2_6_0 = (unittest.expectedFailure ++ if pyexpat.version_info >= (2, 6, 0) else ++ lambda test: test) ++ + def checkwarnings(*filters, quiet=False): + def decorator(test): + def newtest(*args, **kwargs): +@@ -1396,28 +1401,37 @@ def assert_event_tags(self, parser, expected, max_events=None): + self.assertEqual([(action, elem.tag) for action, elem in events], + expected) + +- def test_simple_xml(self): +- for chunk_size in (None, 1, 5): +- with self.subTest(chunk_size=chunk_size): +- parser = ET.XMLPullParser() +- self.assert_event_tags(parser, []) +- self._feed(parser, "\n", chunk_size) +- self.assert_event_tags(parser, []) +- self._feed(parser, +- "\n text\n", chunk_size) +- self.assert_event_tags(parser, [('end', 'element')]) +- self._feed(parser, "texttail\n", chunk_size) +- self._feed(parser, "\n", chunk_size) +- self.assert_event_tags(parser, [ +- ('end', 'element'), +- ('end', 'empty-element'), +- ]) +- self._feed(parser, "\n", chunk_size) +- self.assert_event_tags(parser, [('end', 'root')]) +- self.assertIsNone(parser.close()) ++ def test_simple_xml(self, chunk_size=None): ++ parser = ET.XMLPullParser() ++ self.assert_event_tags(parser, []) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, []) ++ self._feed(parser, ++ "\n text\n", chunk_size) ++ self.assert_event_tags(parser, [('end', 'element')]) ++ self._feed(parser, "texttail\n", chunk_size) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, [ ++ ('end', 'element'), ++ ('end', 'empty-element'), ++ ]) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, [('end', 'root')]) ++ self.assertIsNone(parser.close()) ++ ++ @fails_with_expat_2_6_0 ++ def test_simple_xml_chunk_1(self): ++ self.test_simple_xml(chunk_size=1) ++ ++ @fails_with_expat_2_6_0 ++ def test_simple_xml_chunk_5(self): ++ self.test_simple_xml(chunk_size=5) ++ ++ def test_simple_xml_chunk_22(self): ++ self.test_simple_xml(chunk_size=22) + + def test_feed_while_iterating(self): + parser = ET.XMLPullParser() +diff --git a/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst +new file mode 100644 +index 0000000000..6f1015235c +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst +@@ -0,0 +1,2 @@ ++Fix tests for :class:`~xml.etree.ElementTree.XMLPullParser` with Expat ++2.6.0. diff --git a/python3.10.spec b/python3.10.spec index 2d24e03..8164713 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -323,6 +323,13 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # Thomas Dwyer. Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch +# 00422 # a353cebef737c41420dc7ae2469dd657371b8881 +# gh-115133: Fix tests for XMLPullParser with Expat 2.6.0 +# +# Feeding the parser by too small chunks defers parsing to prevent +# CVE-2023-52425. Future versions of Expat may be more reactive. +Patch422: 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1596,6 +1603,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Feb 28 2024 Charalampos Stratakis - 3.10.13-3 +- Fix tests for XMLPullParser with Expat 2.6.0 + * Mon Dec 18 2023 Lumír Balhar - 3.10.13-2 - Security fix for CVE-2023-27043 (rhbz#2196187) From 8ba4297490170e14809514c91252446da29f9690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Wed, 20 Mar 2024 11:19:24 +0100 Subject: [PATCH 076/112] Update to 3.10.14 --- 00251-change-user-install-location.patch | 4 +- ...s-for-xmlpullparser-with-expat-2-6-0.patch | 107 -- pgp_keys.asc | 109 -- pgp_keys_combined.asc | 1281 +++++++++++++++++ python3.10.spec | 23 +- sources | 4 +- 6 files changed, 1297 insertions(+), 231 deletions(-) delete mode 100644 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch delete mode 100644 pgp_keys.asc create mode 100644 pgp_keys_combined.asc diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index dc9c257..b0a4c9c 100644 --- a/00251-change-user-install-location.patch +++ b/00251-change-user-install-location.patch @@ -61,10 +61,10 @@ index 01d5331a63..79f70f0de4 100644 else: if self.exec_prefix is None: diff --git a/Lib/site.py b/Lib/site.py -index 939893eb5e..d1316c3355 100644 +index 5302037e0b..4ef002c6bc 100644 --- a/Lib/site.py +++ b/Lib/site.py -@@ -380,8 +380,15 @@ def getsitepackages(prefixes=None): +@@ -390,8 +390,15 @@ def getsitepackages(prefixes=None): return sitepackages def addsitepackages(known_paths, prefixes=None): diff --git a/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch b/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch deleted file mode 100644 index a54d321..0000000 --- a/00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch +++ /dev/null @@ -1,107 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Serhiy Storchaka -Date: Sun, 11 Feb 2024 12:08:39 +0200 -Subject: [PATCH] 00422: gh-115133: Fix tests for XMLPullParser with Expat - 2.6.0 - -Feeding the parser by too small chunks defers parsing to prevent -CVE-2023-52425. Future versions of Expat may be more reactive. - -(cherry picked from commit 4a08e7b3431cd32a0daf22a33421cd3035343dc4) ---- - Lib/test/test_xml_etree.py | 58 ++++++++++++------- - ...-02-08-14-21-28.gh-issue-115133.ycl4ko.rst | 2 + - 2 files changed, 38 insertions(+), 22 deletions(-) - create mode 100644 Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst - -diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py -index 940e02630e..c03d1bacda 100644 ---- a/Lib/test/test_xml_etree.py -+++ b/Lib/test/test_xml_etree.py -@@ -13,6 +13,7 @@ - import operator - import os - import pickle -+import pyexpat - import sys - import textwrap - import types -@@ -120,6 +121,10 @@ - - """ - -+fails_with_expat_2_6_0 = (unittest.expectedFailure -+ if pyexpat.version_info >= (2, 6, 0) else -+ lambda test: test) -+ - def checkwarnings(*filters, quiet=False): - def decorator(test): - def newtest(*args, **kwargs): -@@ -1396,28 +1401,37 @@ def assert_event_tags(self, parser, expected, max_events=None): - self.assertEqual([(action, elem.tag) for action, elem in events], - expected) - -- def test_simple_xml(self): -- for chunk_size in (None, 1, 5): -- with self.subTest(chunk_size=chunk_size): -- parser = ET.XMLPullParser() -- self.assert_event_tags(parser, []) -- self._feed(parser, "\n", chunk_size) -- self.assert_event_tags(parser, []) -- self._feed(parser, -- "\n text\n", chunk_size) -- self.assert_event_tags(parser, [('end', 'element')]) -- self._feed(parser, "texttail\n", chunk_size) -- self._feed(parser, "\n", chunk_size) -- self.assert_event_tags(parser, [ -- ('end', 'element'), -- ('end', 'empty-element'), -- ]) -- self._feed(parser, "\n", chunk_size) -- self.assert_event_tags(parser, [('end', 'root')]) -- self.assertIsNone(parser.close()) -+ def test_simple_xml(self, chunk_size=None): -+ parser = ET.XMLPullParser() -+ self.assert_event_tags(parser, []) -+ self._feed(parser, "\n", chunk_size) -+ self.assert_event_tags(parser, []) -+ self._feed(parser, -+ "\n text\n", chunk_size) -+ self.assert_event_tags(parser, [('end', 'element')]) -+ self._feed(parser, "texttail\n", chunk_size) -+ self._feed(parser, "\n", chunk_size) -+ self.assert_event_tags(parser, [ -+ ('end', 'element'), -+ ('end', 'empty-element'), -+ ]) -+ self._feed(parser, "\n", chunk_size) -+ self.assert_event_tags(parser, [('end', 'root')]) -+ self.assertIsNone(parser.close()) -+ -+ @fails_with_expat_2_6_0 -+ def test_simple_xml_chunk_1(self): -+ self.test_simple_xml(chunk_size=1) -+ -+ @fails_with_expat_2_6_0 -+ def test_simple_xml_chunk_5(self): -+ self.test_simple_xml(chunk_size=5) -+ -+ def test_simple_xml_chunk_22(self): -+ self.test_simple_xml(chunk_size=22) - - def test_feed_while_iterating(self): - parser = ET.XMLPullParser() -diff --git a/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst -new file mode 100644 -index 0000000000..6f1015235c ---- /dev/null -+++ b/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst -@@ -0,0 +1,2 @@ -+Fix tests for :class:`~xml.etree.ElementTree.XMLPullParser` with Expat -+2.6.0. diff --git a/pgp_keys.asc b/pgp_keys.asc deleted file mode 100644 index 11dccb8..0000000 --- a/pgp_keys.asc +++ /dev/null @@ -1,109 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- - -mQINBFq+ToQBEADRYvIVtbK6owynD3j3nxwpW2KEk/p+aDvtXmc2SR2dBcZ8sFW2 -R5vEsG8d3/D3wgv5pcL3KfNNXQYUnXVbobrFUUWQYc79qIsE3MgiPf5NVOtwKPUR -i5g9YJgKvpBxkQfqp3LYGm9ZBtwo3DVLA3yn7KsazCmAgTNFJYw7ku1XxgmIzY6K -5J30DfbJiqDqj4f9GslCCCCH3qiPnuLG/HUyVLHMpbWlaiy9NI0GcaLxjJewHj9w -W2D2lydkxe5JGo7egUkV3ILcuLVSVKA35SKY27dYqfuyqp9tAzaRbjDYjsYdHA6G -BqrNrKBn/GwlFDPrVdcvN3ZSY2wMLTxWE3Axc/FweuHxFnou/80FwX7F3JD+oEQ6 -rofmcxOBCC7J98I7HZAhP9jBn88XIS2hztbLq8d6rZJZRtcz0k61VR0ddO+TrFmf -9rMYCPgCckRtVxeFIVIabrN1IzKynLFeo040h8hSGswd6YKDOVwjJY6Oa6EmVefZ -a8QSt4+M65RSzH6SEPY008F3nJUAK6MEkzTak+tFltZNrVWu8p2xd1j9nmxAwEhZ -/lgbxLqzYgaUWmfyHeZ8yVA0MhHzdiAL8nVUEdG3KecIq0RWCJLGLWWIjd6KAJl1 -yAmhRYKK/sjPDsL3elHsFACfZbyx3o5GGQNlas1FYoPLWbaNGaJtgFTF2QARAQAB -tCtQYWJsbyBHYWxpbmRvIFNhbGdhZG8gPHBhYmxvZ3NhbEBnbWFpbC5jb20+iQJO -BBMBCgA4FiEEoDXIwZIZuoIezqhrZOYo+NaEaW0FAlq+ToQCGwMFCwkIBwMFFQoJ -CAsFFgIDAQACHgECF4AACgkQZOYo+NaEaW2bmA/+PXIap2udLoUVOHxnsIBdqYwp -sv1Aj5lfIJmNhmxPbHShwp1Jg+w4urxe+2Dj5ofKVlIo1i83bQkvnKJMDXDVuc/K -P6zqhBJ3rT4Q3qx2mzX8bIfQoJ2JHuH4lkP+I7doDcHHRyeNASyk72VdQmU4twNw -Ibn8nSNV6ThKHdoPYzVnO2rZUFcGIqH5HNsvR+B7cc1MBCHsgURYwSVhSePIFGlZ -iasdBD6QQkDSe4QWi7AcJFWFElw4kbOKJWxAWsrEk+tMXJVGRjnmL289EmPCx/vx -BqKy7Mse0yWCSRR3vB+O6TB1S5SgEyEgqlYsfGNv1qf/rfRD4KkyCbNU3LhY1Aim -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 -=6Zb4 ------END PGP PUBLIC KEY BLOCK----- diff --git a/pgp_keys_combined.asc b/pgp_keys_combined.asc new file mode 100644 index 0000000..c23278e --- /dev/null +++ b/pgp_keys_combined.asc @@ -0,0 +1,1281 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFq+ToQBEADRYvIVtbK6owynD3j3nxwpW2KEk/p+aDvtXmc2SR2dBcZ8sFW2 +R5vEsG8d3/D3wgv5pcL3KfNNXQYUnXVbobrFUUWQYc79qIsE3MgiPf5NVOtwKPUR +i5g9YJgKvpBxkQfqp3LYGm9ZBtwo3DVLA3yn7KsazCmAgTNFJYw7ku1XxgmIzY6K +5J30DfbJiqDqj4f9GslCCCCH3qiPnuLG/HUyVLHMpbWlaiy9NI0GcaLxjJewHj9w +W2D2lydkxe5JGo7egUkV3ILcuLVSVKA35SKY27dYqfuyqp9tAzaRbjDYjsYdHA6G +BqrNrKBn/GwlFDPrVdcvN3ZSY2wMLTxWE3Axc/FweuHxFnou/80FwX7F3JD+oEQ6 +rofmcxOBCC7J98I7HZAhP9jBn88XIS2hztbLq8d6rZJZRtcz0k61VR0ddO+TrFmf +9rMYCPgCckRtVxeFIVIabrN1IzKynLFeo040h8hSGswd6YKDOVwjJY6Oa6EmVefZ +a8QSt4+M65RSzH6SEPY008F3nJUAK6MEkzTak+tFltZNrVWu8p2xd1j9nmxAwEhZ +/lgbxLqzYgaUWmfyHeZ8yVA0MhHzdiAL8nVUEdG3KecIq0RWCJLGLWWIjd6KAJl1 +yAmhRYKK/sjPDsL3elHsFACfZbyx3o5GGQNlas1FYoPLWbaNGaJtgFTF2QARAQAB +tCtQYWJsbyBHYWxpbmRvIFNhbGdhZG8gPHBhYmxvZ3NhbEBnbWFpbC5jb20+iQJO +BBMBCgA4FiEEoDXIwZIZuoIezqhrZOYo+NaEaW0FAlq+ToQCGwMFCwkIBwMFFQoJ +CAsFFgIDAQACHgECF4AACgkQZOYo+NaEaW2bmA/+PXIap2udLoUVOHxnsIBdqYwp +sv1Aj5lfIJmNhmxPbHShwp1Jg+w4urxe+2Dj5ofKVlIo1i83bQkvnKJMDXDVuc/K +P6zqhBJ3rT4Q3qx2mzX8bIfQoJ2JHuH4lkP+I7doDcHHRyeNASyk72VdQmU4twNw +Ibn8nSNV6ThKHdoPYzVnO2rZUFcGIqH5HNsvR+B7cc1MBCHsgURYwSVhSePIFGlZ +iasdBD6QQkDSe4QWi7AcJFWFElw4kbOKJWxAWsrEk+tMXJVGRjnmL289EmPCx/vx +BqKy7Mse0yWCSRR3vB+O6TB1S5SgEyEgqlYsfGNv1qf/rfRD4KkyCbNU3LhY1Aim +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 +=6Zb4 +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFVRJ0kBEACko4KHmTBm01lcf4IsN4QxglIuf51lYqHs9B5nQbO6OSUivPXP +QBq3fu69yellpQiWaWhBvJB1s91sVuP1G30hcwl7SRxBUNQUUXT7lliLvhXEvcAb +l7iyoi3MsCdIcDdJvdMSMcbCJLSBDl8hETWcGj6Mnoj/HBr0r8IYmLf+cnCCNFg5 +f4mBQDlgsXpSjiMulprFwsEUctaJ1/7V0cMvXllsyXFw6lzd9xvULjih+C3eiKqQ +G8TInOPZgaWQSYKr5ihoVFZViRm0mlAzZ6/h9OZ3AeNJ4LhtThw6HbhNA93RkMx+ +zt6HeH4e8QGQQK5KZf4Kt3OdnTyJ3cOnLy6UQAzQAsmcFef7DwbbEQglgY56k4z1 +iB0289eJTIwA9f4fJNjlw6wcuUaGQGSF0yPYDq11PoZjc0tSUM3UxLeqwZco+o3e +oQ4d6bKEKmdHLyX9Hkg7WxXOqylNm/45roFE1d3STCt942n3+gRtOEGLmBP02ad1 +LfjOYNZyjltv2fo6xAaT06/YT2YuhgTL+aOS9nLtZ6vbV43IBw6O+xmBBZDM6Cbx +SNN2Bzu1HFij/wTUuX3Dq8cSCgkK2x/o1L5u2fBBDr4iMLthI1TFhVF5B6PAgV4o +86Js7ww4xWnXpwqXlVE7xUHumGH3IDfYLuiKxWx2ycfNJEBF807g7V2XBQARAQAB +tC7FgXVrYXN6IExhbmdhIChHUEcgbGFuZ2EucGwpIDxsdWthc3pAbGFuZ2EucGw+ +iQJXBBMBCgBBAhsDBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAhkBFiEE4/8oOcBI +slwITevpsmmV4xAlBWgFAmCRdaoFCVYwHhAACgkQsmmV4xAlBWjHPw/+PNwNDTSF +sV2pukpSL1HyiUzgwdHY+rxYQsadQr4ZStNG7F7XScIQk7kNXqbBD9K7G56zZr8r +fTPUdxHR3ApMWIFzL0A2ry9QrqRSYJ9Vt/hWJkWYMrsJ5YOkKX6bPFUjqfGT4vRk +cvelmRBz+zTxpm1cVmZPPLYcwhmZ3lYFTOP3A21dILEgxdYKWZRjd7/DSrTps7tw +nFCI5R/+1TYuOvrQUHY3SIvXyivwRWAWZwEBYsrUrEVKw6ymgqYnRWwn1/5yoJv7 +DrshVIR9drdIa/tfYhlc5G3m1er1vC2u78Wg0gQUrCknBT3a4+bg/mNUmIQcJDj/ +IhWPUo+bv4XEfP7DBKfhvhXsDtYR6KlaIVKHtF/F5EbT4M3bC3hVZjz9ijpfeRWF +lx35kGfyI5PxU407IcvWLKysM2PLD6cFjzRpi375I2UTTMBAY8/fQiA9j/h8ke1F +kuQ3gAq4dAHxYIb/FG15WRmq75e/SRzq1tCyhwiDcr0mLkpDBJ6iCl1Yo5OyXqDL +qpuX1+XaLOM/TcTYHRNMMOOeWWPJCab8NvAS0CoaL0H6HKF6yO/bMLdgW4Bhi3fK +5GCy4TdyUjFEQ66n7vWE4S3D0OvdSOvrmi/LiYip2GQX1QXM3VBwMZFvMfzBiD9R +varsPq8cMWgUOoVX/V6BNonjwGY+9joiCPyJARwEEwEKAAYFAlVSjkoACgkQ8iHF +0sRizfhLQwgApsIjObXyMiEtNg/QRdSPdCm26prakbeSBjzXm68lk+kchhUz15p/ +7BkvGjetpGWvGupnC3+dJTOZ5HQYZVOx/2oX58MyVYNl+izbooCck+QF3DLoJZ3e +lqUlzhM4+Yn+JciGcE2WMSH052edU6wSM2Qv2zgBaZWf355afRZeD33rsV7hdnsV +hERmnMvWd/dkX3bGiMisWQsx7PcqeW47r6BiFDNeja+Vo1bjBbISGrn9cq5kNG+c +zY26OS71MCh5aEhHiOCXeUN6Io4khG7p14RYEheeNCA7Dr68JwnRNkS9o0Wrsjkm +5zKqnEckUNis2PrT4ySXRrB9wd4X1PzGxokCHAQTAQIABgUCVVJzmQAKCRCZtd4L +MJZlaXWID/9l4b5eosARYor3eEPdR/oovUzPY1fY9KESZw8yHfRFUi+qrsSYnYKJ +gnFoJ8OJp0SAQX1AI1voq4NOCVlbZN2im9jmks/eDYg510u73s7cwmZfKokyxVEL +Bo0ZA6e55s1FF+10JP//tmmCryLLIDv3/FmLdDHY04nAq11FARLRX9BoQzWSwl/u +AKsFJeKvFQQv4atV5fsl58BuVppqdg1A79lT4SekAlGtCOmO0h1/apDKoVYtHeSg +8AZjss3DKNNmFDJtAkeSRSgmojPe3lplNiUJoLgcPAOL1rhRIKKY3YieVs54/Ecd +W3KKUtOm4qrpobuyzEJWmrbeiVzV652I+cLML9iE5dxKjCNP87xBLaPKQFJbBDKf +XTJuexppiQJPjYPWt7/08odIFoM6OKdz2IVnjlYvBKSbLxmBzNIcNRK75eQCnIVl +MRfKtvAOOUGdl4Hzrf0eGMQtPcDhsQErv9hwCuV46TcZNw1jpvI//jGXKueujIIh +/YauFUP2rMWwX0vRpi1+mFnulLDewGeh5ORc0nJTEeDOq60lzT7ilnbCKuQ1UR4y +Uj2EQMyqHF/ky5dg5QTUmkTuk8f2T8FoibgF1QDfWS5Sr+W8EW4YQYzJKE9woFpl +yYH409EDYqvPbKQogTgBMtptibQBBjUnl1SiXc0XlybUd27C4KTvC4kCHAQTAQIA +BgUCVVJ6bAAKCRDg+ogVk1gtkZ0ND/9PYWzAKLIBV5EzQcoQ+NdQXcqNv8ROel1S +e4sz9h/FCI00JdI/SvnBs1JupECaRzFYT99X4UtdAsLYlZBDMB97C7Vl4Yy9Q0PM +61GZP7iANKL2JiOyKXXkME8Sk5ufVdRwBr/Yb/Xs00zMj7X811j1qqmEdalRNaPd +mRBL4kbrkmqs9b3ZeJlZtvasVT25mrR3Sh/D543y4dvbO6UiJXJeEQrLsNTszPHI +hBwu4x0hMgtfTqUjNodZ+zeUGNNe6ZT3QIYBgLGrCoz9wGMyUtX1RQBNoSIOq+aw +G3r8/8SzNNtdUnfw1NelBKSmh+V1KIpUAc9/OMNmIAEcO4rTJsEE0kL3sRay9lzO +ihpUyJMM/Z9FTqsTvKc5Wi38Vo+R07dapUBLS5TpS89+pCffaM9snQbuRfmhoCuf +Sslp8j2OSRsFTq5BA84gmQNteSlwuXs6r99EV3sQftrDnCo7AJJKDVeJ8gghlIYG +TMYrpVjsC8Rej7DxJa4fWznXhdtediFzGldQ+nBj1HlSeb9Y1ikG0ZAB8jnVDYeP +u5DtqL6AbWcr6n5evATlq3/YieDPBTBBCfZ6wAJ137gaRlPsjTsBng4V+sXUrQeg +S3D/IEW/qznJiEZljzDW6Rx+cPmMeKRdcEpZ4zQuqAbgdX82Gjn1tiAzSx6ez3V+ +2Up9RRKyAYkCHAQTAQgABgUCVVJ7xAAKCRDetUdYIbCzY7qwD/9Q6RhhHMvzV4Dt +/QYMiRwVEdo4XJxPZJfcpQe3TwyRsnS+pmMuLL2k5emLufzomXc20Dx4StHOVRv7 +ZZKlSrIPL1d4u3DFygL4mRg7BIZWEmvtWZbfCEb3Kjg6ugh/+E2tt6sIRmSSt5lk +OBsuwB8FyllTuiWe+pkkdESL4j6yRUDv5xE4jT7ha84aq1Rq+fYoLx/NKPAV5xHN +xr2u7rHL6yFn0IRqu+1EIgDqnraS40f07OoSmE7QTsn4XWAm1XD9HiOtHP/FZKiU +Pmnm0C0QLvMf7mP9cENkFP5GZjqxMO9HS9NWQolpato5ndcWxIn5c5oHmlVR2eyq +o4NBC4mu+l0I6dyR+C0Kk5koEE4KPFxCeXXXT9h7O+aeOs/eZeQuI5vCp09MUPUU +boAPzViAMNJOCKPKwwl1p6ccDA04KLKDKhL5Gt6JLosoD7G4nACUusRpyrXwihRk +1PzPB4+2INEQ0C96DcnEGkMwMy8SVzxL+bjVbQFdFg5w+OicvDZO5xrQWY1CBdqO +W9IGsSCc7g/y9DNU9dgNlm5kLnA3meEtHWIYgTFHuQ8uiRFfSgCHn5beMIzSs05Q +8Qph3gvAwflDmsT96Qr7woyFTKwL0Ioumoz1yRGRhMuB3oyd3A76Igd8ENOi3VrF +mGVXDYCXFFgIOhAo1k/Q/Xf8P/tu4okCHAQTAQgABgUCVVJ9hAAKCRD/VOEuHKYZ +shfsD/4+9FPhrHb9DBeq7e13QJTY8Sin9uFin2wTpH/9Qh6eTMd1PeF825CfrE4B +/zFK3v8v4MfdGzGvu9MaGHedKc1RN+rusxA9v+EVX1TLceAJNhTTMaphlJzMn6gn +kC0wrgdmCmspnxT0DzvCfYzf4vaGOCP4cHXOAvYqz/U/BK1t7Nuf7tmyePRn19EQ +KJzvJA2K8Gqg/v4ovYtKXtJYA9IrCK6eR4Y7A+mKUNzGrb0poDcYp9B1CxyhRrsg +WHoNUIKVpVp1xSOLr13Z1EvG0Pu24j8Ygz+PuEIPaNJ1vsCTff+fDT/XjI9nBlZn +C55khg/r81sMKPIwYH7eTKTUmzyUHZZJAn6z2JI38KG+nPk/ln3llHhTWelh9H4e +nD8yHzTZDrXuiRCZg3W8fI5StezmrjORBCE38fkMB/TL0IZdiY/K9IPgcPQEX8RS +LwAm4uua13qCsVy18BhXTRshgqAwwHyd8yj9j/H0vvFVU1thapOB+aMLr3w7tn5y +msxGfx+A933s8AWXLs/dvdr5tn2LQj7ZiCTqPf4elniVelwFL5DqhZ74ZJjBmiIA +VIykEVonH4xOneiFFH8gz7/WT9V/Mh77fnqLk8CTM7DPZLskdL2DCS4zqcMuviSs +zY35n8BJYZXsp004NQeVut+mSLCktPBdSrRb956dMiXuMgVWO4kCHAQTAQgABgUC +VVKEKQAKCRCRPzdd5iqXDJvFD/9bhqFIHOo7fwTbEg5Chb5/vPe3hyS7Ciot67xM +jPGGUWree7l9LytmLvTPJdXfcYehthd/JCB2YSMljfPUwrc3N8uahxDZ2KnESByG +4FhCkzQrQBImGCBevNmsy9SfH3G4OnXlOTaozPz+RkqYvfypczzbV6B/f9JcXcQR +YwGmTloohQhoHGGvm1CXKNgbEZjSRYaROpJ2NCmaXroe3ZhvHxd+d2Z2pQUfZX98 +2M7mjRXTkqzDjdhx5j16bi25ZV+1JDiwul7O3TWFLY/VQeK1YEpWuDbMSeSlf05l +5RsHR3W1nNThmbAf70SmqO0rvn8Idla56Siphl+Wbl8JNpM9YyWrb0fuf3o3bdS1 +uIrQzO3jiLA0DzBfjX2LEQ5JKm9M0fZil1R8MDMRZQFvNryF3Z1kl1ZCEuwUNGow +F+U3yepko/E0hNWKDd7lmtRZfCoor5KTI54WzqOg2lsDnq2Dk5Vbf97qJm9fy105 +WXMSvgIOiNJEyOvoVlN6gzA+dQ5bnuz4eKpq98I8RiO9DiCenyMk1CXSYUj0+NQJ +YU52l/f8x5QteiENGFiFwfMgZbOBuKTKL1iCp4l/RbxaHiYxc55m3mIqS4U60bpV +3be68Cp7m96kYc36osRh948SrMKPZ6Zb3QrMYGOxiWL9eVOdSOYWMwf3wF6VGd26 +Nfk9sYkCHAQTAQoABgUCVVJ5bQAKCRCotR9egDLM5JM6D/9cyvDLDOwZuH/q8/eW +tV5S3x5V75VdrjnIma9WfyTqgrv6v8oWV7PoQ2C3Rd/DQxu9ZiMxncj6ctufptes +IMCm9trlNqbFdFzklBg7LTzSXnMOYxpOf+xYWWnrzBR4pgF9DO/zsr71x2uKkQXg +bKbz+8O9/Rx6/h+33c1CPHG4gc5OopSLStnnltOpRZ9P7q3Rt+CJLutXI3fBGnBR +Yi2NOAZkszlj1yBZrgVOMvDZJJbdVR5J1nFCYHbowQD6X0OBtLwksfbnfcaJRr8q +0j8/4130eWQ0pT9CZ706JPG28CZfNJo3UtFlH2jpXAh/G+b74fdYtoMeKg1z38Lq +Vdjm19hoyYXMDiBoHKpX9Xd43ZZU++DRsS79EW+e5a6stUZLUYfwlwXPNkCls052 +Bzyqq6NN8KHUFhbIBVrRWxKJRJ3/Wo2uQJZwUKKoinSol1jHfPkc58pDOXrySaX4 +HPcaFoKWtGObYFsdlCDw0P7IhFh4I2Zus+U3kAqaC/DUPgBzRNI4nlq7ukHPy16l +Stq/I9lPxN47GPW+qb0EyewarV3JmRyag1BOH9BINBnR4/q6N9vbYb73D3Ttf18B +6K57ZKjQ48qeDVKZ3W84kZExTR+3b1DeIAEjlq5a4oHvUo1KfXXk0hePx6a2QJij +BaqJ6y0UANdCFMg5nOuckRpsgIkCHAQTAQoABgUCVVKEZwAKCRCt3ULg6XStj1Fr +D/4+J6z+z4I6GTYdm6ET0EDVkO4/ZQHGVMIoIvzhl3QYTAeE+r44OuMxSAxO+B6r +cgNUNjmbvqLaN3x3Syree76hBcqiZSKzT70t1OqdTMwQxotRsVMapwk7O4m7fthF +3eAgumZguYj0zzicHoir4IahlVOgWR7AWHA29wsM15wJVjLiIo+iIhX0okQAML92 +4d9BqEZeTB4+bV7UcH6AAFyob6cDZexkLwN6ydWNpXaMREHqGavbLdlkqmGhjVre +pFxIIPEnQsxpmGIuWaDhgcy/W0Uw7r/gQ8UHa8rzQW4+0SqvBBFTJknX2OlL35ZF +LwEUglgvrf15LRYCu8Xi4EMLULIMsCz6P1B8MrNpN/tPQyLQoKhbJRAow7kszL4O +FbCma/8nZMvZyxQ7tT52XjBagNnMCfshsr8p3UtsKSm1XkIVts8t70U1cSG+kXtC +yzs0wsNV4UH/HK4S8fiKkxTYGIGDReFqtVr6LTGOJl/6+T5z9Az8GeYK18HXU67h +H/z0eHikvem3hxSJZrHt4J5vfC15zyrhSKLdmij/pxcXjCffU2fEJ/Ngqk472EAQ +2k0EawfOWTShdsQ3yeWEOhz2CW1a9nJiAcavJtmSo6eFLK/hFCJllvClsKddpa31 +TTc0TTs6gLnB93V+tw0JlBrueNErAgzCE7qhoVDT45LXoIkCIgQTAQoADAUCVVJ0 +bwWDB4YfgAAKCRD8n7XhIU7pK2pVD/4pjC7kxq64PCKDQO4QNV/481TAVXDaE30t +kAX46waCJEqsT11hLKnYS25bD+DLXQreYSxEMV9lvSGHqa/mRG18Qw/MdUECO+Tw +BCmeArGw7EnKuLG3jrppW7/ycEvKeoPRdkioliWlFzIzfrB/tfYmiCb4W9CEDEZh +/5Mb4jQUMMLDI0sq+dcvtmOrbmSIDTCnPcvponLtxkmDtmMpgayUUCWaE/3h5jgG +Qd7BpiXE50IVD6lpmsbSy/RiiCKLNjI+yhw0SJoLZ+MhDnCDuOMOKOW8TECKm/iX +nGe99l3eas44wfP6LSttxpwrRlorgv0rT7LAKYC2EqwwVgXfGtYUgjLTfCUjGb+9 +A7uMC+L5pCeZyRGvSUoulBtmmg4I1OWz3ACV3iB43y4t+G2LKggkjgZep17Iq5KW +KzWlG8RhiI4aiMtQLl+ft267TJTkKLX7qGrIYjiYQnmtriGgq59AjWoNxOTeCmKo +CZVto7lncEvJHpj9N/3d8ob+F1FZtIgqGIYG4DJwRbPMw6AOLpXQWgwKhWfwJrpv +Rd8l0FIKfOwhxhCif2RAAqxmTQKQF21Bsa3DBdhs42xscpTiK4LxAMhZk+CTZpFv +fFxxdHFrcUbaz2jqt0LGkh4NknHEM6U+gqTksDL+tupk4bq1GXaMtzUFzt4BPDnS +p6yN+311qokCHAQTAQoABgUCVVKvOwAKCRDgldvmp8WiZqHdEACx+sFSXzECtHly +EvhzD50T0Jk3s6fFDfTNr8oMnboNvJdbwvElfL3uaBClwmqFlzjPw3xLb9kWanEr +zXfdVZsZFTb3tmzI5S86I/fRQyk9Hrgm53OUP1lTR2JzJGUwHoYc1m/8RShNgdCJ +aWsULsmKIAVxs7u34EdqlURqzbglh5lhyeKa/nuT2dDU82R6a9//ahziIwOFlNrH +zlJnthCpEdjutT7C3+pL3ohy84K60G2csEFwnyI/3CZB+rt2YM98z0QASnR0cAGG +RPMT/rGcRUeW+XiGzt5hUAexJSfWYA+M9do2o9sDiw5Ic7+gi425Fciya0z1lLMq +VFY2rbs7abm1Kqkt19mT1S52f491WggSS4IRJIvKJcL7Sj7Jk3fM2jaVllcxtOti +vg3rf83Ke/f/cMKKVJ7noExiVlpZabZY/Wl/fzrS5FMN3km83dYUhHh4LlNl/OkP +3QnRTwS1p5vBJuVytEHLg6yv6Ae6kPu4TzBkol3lP3+YSp8pPh6ZP9C+jDzKbNZu +TcP1htDariF9bZf0XPLr4gn8m/6TbjO6ezbB4IMENnWzAL+23nviDE8kLlW0ZPux +4hZwglBz9FHdOO9af1yDJgvwspe9IKPMqGCcZZ4ZYQ+7y9Z3mvzaVPjDQf2oPSGA +I6VvQy2pQtauWlBajtmZqfid6Q4cVokCHAQTAQoABgUCVVN7VwAKCRB1pVGnIpXs +H3rWEAC2oQ8aWe4aiezCgD4oMnWlE9UXwZ/ZYNlYAp8xQvbRr3dZJ707Z976PlGA +suJIejR/+IbMJUVl40npbFCiYYOMoqs6PAxDZsnuymW058WXFUSlBbwXq5w/2o4g +Qxy1TksQUSZCx0G+tPGilegcCO/5hzPgKzYNKQ1mg00TIu+PRo+cDR42Q+tWRAmt ++9k64Z2IWmA1NVCMAGcCC2hU9nr9HMTLXZPZPRbzL4TRygafZTBqCd2pC1YFupER +4Htm7yd1Xnd3nqSVYU4e/+wU3K9U6fd4qWIkSKP+F+LDqND1zTM1c28YB+WsMYXI +/cwEKjzOJsIJFJbZUdN85uDx7vT3zDObm8iL2xnq12jmm4G2m1qWVfPCqL5giMSJ +lrPQAnrYxePVvxqfDLQcGKSXW3J4VD9yTlAL3nn+9Lto2qD89FU9ikfxhQwB+BBi +SHNwXzyVs8fAlkb9+v8CjPXEaRJiU1lW9xyrcYbQy6O6Au9EpE0aoac/x1x9kliZ +1DEHmM91jJCONQDrVlbXMO9W+2/uzbWB/PtWnHSa6gDPxLld8BGvoZAJ03yc9qzy +kyz86Rg7IVuBKMA+PLRvBZsfJDmCs8wu+KfBPFNRqFAjC+yGE7v/JE3RF7fdBcQN +LvNernASmVP0SSg9NnBjAh8uhwpphMCx0ckARqBF+1gMUavaZYkBHAQTAQoABgUC +VVOLpgAKCRC9AM0evEl8/asxCACB269wUL4VODe1p8lCLiuDBPzFXnRSrU1H4udg +JD3F7Jlqc+6Cnb2SCHFwz3i8N/4tP/TMkrQoDZgNy3kQm7SWSDSPKXDItn5XieP1 +HJKMrvG/DKT5QV5JMnUmwZrsFgo7iNFEhVnH1WkWgGdbvRA7hoN+O8ruFl5R/V2k +1/17hZ3t+FoGd3jncigYbvrFwRLe43xfbzVg5PV/LUjxOsrCbix1XC1TbDyrTt7+ +CfcZSQvlCQkrimEGDDGlTvGStmUfkLaAWBp+PyvnaqCQ++KB8H3CW7Kyga5bJ1wX +aDU4FdLjYs2gyF62uKkqIbUk4NFPU+ggWdvmOuRloXm1gQ5jiQIcBBMBCgAGBQJV +VtEYAAoJEH/Z/MsAC+7u2JcQAIbVKrOXPxCNIxwSFjPY1n/CzGkFbTi4sTVsT+uw +NRthmUlG6Q089/hcGgl4bIUM3zTpP1IEWi/7lPwJKUPOeYcy7gNImVcjxqQQRiSb +WEey9ojsEu15ljuc9za/+gVpiD9e1vvOGX83UfN4o+L6MiJ7fJ632wL/tyYABTzn +nHtQSNOklsLOLpKg68cTUMDl/SlrXngOrNHVS6/bo+y34cTyEdKFkDT0KY4dBOUl +3DVKDAzXdkq14x2QK64g2hTX7Lf1654KMQgjvYMus71QF6xwdn2sm36jcfUAiwdY +RUdN+BJ/hfkDkxdMdQFL93Rm7z7d1XHMaIynFWYbN5FTTj7XmgyIn9ymZ1nMDQfr +HpOxyMuk/SQgbN1+zAFRZQhTNFTc7swDg6wj1/4iI+wlgsevhzFDS5Fg7K+aW1to +wBwPVg7BakAYMmFGTmvYZ2bJd7CeTs9JPSgKTuQAhzd1K3xMawg6GTtLlHmYXxWP +vvB/uQOieiWGLpohziNBbuvtzOJ4fc53B7Gsgr9pCNBOm8/LRtbNQP2opGA9dNkD +9bI4EvlCHtFB2Cj7mIluN20HiJeeYAZIywL9LhIwzFdAHxPEdp5GDg4Py/CIYUkx +MRJZssUK2Kt5eBDvxj39ac1u1XZbVmH8pS86qafKTldF4TsuddI17un9H5VOm7iw +whLsiQIcBBMBAgAGBQJVVn0uAAoJEFjhG7HkFNmt3s4P/3D1Ad43N6T6pLhxsCgX +jEMPzlEbNpiLzpNi/ub5BbCDti64nZVaa7wruGeBkmHcpZFTlDu8Zmp39Hx8BwKy +WxlGcWuM4OcLLeyZJ0Xdil5DYkqaB/QY1BQSa1UJQv0n3itHp6vj/KhxY+E5ykUS +VQKTyIk/IMV0kL9PcJNrfq7PWgjnB/QMXra8EwOM3nJ758pw9dgoF6JRkf68dwYW +jLL8fc4rVN6/JO4sAwxrqW4kn6r7186/M4xEOkQvIp9S21F0vLAjqk2zitK6Mx/2 +/7E0yOA54foYqy4xfv8Da2BwIHShmpBeHbM5pNIXpAwqrCw7cAhs5jXpVZIPmnMG +e3rZ6HK/w8qezwzA9Z6Ahu9hf5X4/bGewIEWLV/tprzIrBBrc2H+7OT0gSXKr+cu +C5yIxDnClMllo1p+ABy4csxmDlih+o+LqDf4eEy8hm6Bb97I/iG/o7EBvbLfzzxh +s4pbd757PLCcBqVdJ+Mm+CqsQLlixgMkziswvnpZ7ecUk0eMQrwJLNdrCIlnB6kZ +Wq7Kiyn5976jaUCydSrKRxgcqhbDkoY8H1pO68LWnyTdC+GbwOTJJeNEQOeY8MZG +5cVlJrPTrLkB5YG4zyvl7rb9b1NH3IpsmlDBGmr2gSzhvMk7XLKzm71IrnMAoJ2B +MyrNdzrkQ17Qkvxu0UDeHA3niQIcBBMBAgAGBQJVVY7fAAoJENRPy87OSW6u+1EQ +AJi0CL14THhTZtOBfr+otxIZqDkPiaVwtax+WYjyLt1VOgeDHPsEz5zaJsOdkLWD +I+JxuNUef7XxSjF5ALVH4ykpWe2E9r5bMRXc1oBFqxDmwVK8d5uh2in2Y/UdIzHg +5LKOhJmLoCEOhHAIBKgZJkwgznAnsW6/lAKPyuyH5OsiTMtIom2q88aZU7o4bpnZ +yzo3iTsWj9b0oMsn2nlNAqOy7I1Qku6ymCCoAAeY+lyhMMIt4I2mQ6pAcJQG5LFV +BhKuW2LQb+O/KHvaT4/tQL/y3B5DiSYQ2GC8VCMjcadpVV0w6oIodN5Mo5d/drpG +4bUX5TCHfA/1aZVi3KL1sgAISqswvc7qksVyHlybA4SHHZFiG1VukDDCvqcwHp1s +zTMAZBIN0sXqfR1BqS2YqlzWBxXmSYesJeJYJ8vk7RJO5JikUsuj5MPKu6jVFgEB +UvqCcDB4wYBViKjyBXS8vwoewcqaow62by+WXk/R5gynVsnME395yILEsvwW5BBZ +cJLSrI7Iqa+1iD0ZVKpknhwbsKgNcMnzqzDXMflWTUBrzhvjx84WDPfHJXPe4MMM +CIDNU3IrDt/nBN0JE6yOKfnYqi/njHwjsF8IgiHKKwssMqfKFuUBk5f4QSH0MEQH +JU7lNIrqxwjlJaaU7iUNFpRDLTIVO8w9JaxVMhH8JXrxiQIcBBMBAgAGBQJVVUVb +AAoJENqUEEiDhCgm5XEP/izyBXdZFikQkw3ewO2rpu3oZuDIx4OC5V4rgGEaGWlq +wSzGq65M5pXk0LUSU6gb4BAQOc8j9BrzHbN5QzMKxmlVWjxTfUvpq/rHtmNOFA5x +n3MolbRdVrQz/dGlMAXJQE7DvP8YDVCeyVxZsU+pQan6QoYDoUG0snqpwHFicyEe +PCzpoQOFEx623nCn+wJwMPrrPM+T9sFbhYYyCsxVkAkzYiLhfKQw6s3tm2QYDTcd +oU4ZJ63/gmSzQuiRBm2hF8/cH0dpQT1zEE4+nIcffGKcjCeb8JTmVAzf0vMRKWS+ +Ntotklh9HdVxgSBcU6NKOxH80JHABMwI0OakXrT+MbjPSoy6SKslrRfiXAOCK+/6 +qYCleqtdj7KbauCw5wWC2qRyDU9NrX27G45Xc/GXlEYHNIg/SDKrcbPFzr38TQRu +lpS9svtsLb4mFamXwZ+940AMMXyY7qQk/+1yXpOossYsA/WbutkieftFhJQJFMxY +UCD6IeYQZ9zxv7tcvjck9+K2Ap28h/nWLHvB/EBHgNKbkNZgggT4+xb/3/YGcXTB +jS19VAd6la8YTqRRHuHI92/SMDOmkQDGZ0e+u0Tak64sT/b/Sw67yNbY4BpF0rkJ +PaHQTL/rgXPpqEVTHA1qGVn+KFSFfcPJ9ym1UMrJvkfymP40Ina3qhD15rYrhdUj +iQEcBBMBAgAGBQJVVAc4AAoJEJlFM38oiD7LCHoH/0QsEiyxY9Ac9Yjijdbkjm8S +iYv6eHtlFUf3vi5NLqJgxj1H0PALzP8fswBBPTQmM8bjrvPlEJ4Tg2DiILSXDXHW +gU/gDo7fgy2VtaL79TrImXQ7jNUFEp9Np8haYyY5KQjVJITCES7+idi3q+0xtEwe +0N6plEnRUgd5yOv3dUYGwQSPk0uewhR0UxCHOTYvngoSGDJO4ddHVffnmpj3jsvK +vpbUi5ryWjKMhI7IcuJqTwVE+tL3YB2fhEGB5Z2Wor2xzB49kPlR/OnG3QpSRUQ0 +WfvdEhL8kH2lhETwCh4N6+1vZY7ufC12iuqxl48C8mXkeot6HhWqLIzUIznlxdaJ +AhwEEwEKAAYFAlVTwkkACgkQT/CPqhhgANTRWw/8ClnjO7ltJu8BbkLR1FWEpfuK +m0PWOCoRkgcr8L4ndxFEdWapvrEg0VNUMSnBE8E1kai/cAWnwXhYCgi0atDYo6a0 +ZwYLxlC9iu2t3zI2pXiCuW3jZLoFgFP9whQOkuT4VvdcVGrzlrcPNKdXNhNiZIIH +rmTfxcx0pwPsuArOZvrfQJ3SpewKHugp3JwetUkiX8le3hG509HmiDmoWu3xEYIw +Pd39Mm8Qfvyky+1vY8lKP6tvAmIJ5K0IOGKqHGOs+GbNZUMayoISxP9/tmBrme4c +63UAbS+WGoOCRvYs9eXzPEl8aWxORXRpxN7CuU+P6VrNP5Ks2w2vbz7hjr9C2GGE +CKSuByaeOEnAnO2Ttj2wRwhH0eciN8tFSsMIkpsPnjMGZs8mGjg0G8QHYE4gjAP3 +r72RrmteXpzm2JiAWkaX7WwSFZIrchpgL3HyM5FA8FKZ5vxe2P5D2PcUIsoTcFWy +xf1d3Rtx3a5L9Dxx45bqH7oUdCKFasvWuVBi6wC9zi6f2y1sqdNOqL+aMKELDPok +GC/tPXVrmEJnqcaVlx2HF0WCFS3Zgo4s0odESr5iyP66UonqIsJ38Vs6zHKpP9iu +WCNpCo645t9Bkz9Lp8SiViR7Vy8tA3bNFHYEiigp++gBRYRLDygoBjuoGd80wBUD +aE7Fc+gZiXRALsWNmrCJAhwEEwECAAYFAlVTotEACgkQgkM+NYeyrn2c0w/8DGbK +Wk1KhQ158XQp+A0Tl1hva0pE98sNrnc/K6ZSChA9JBRvYW1RoSb6HdVxxXLZxFyo +Ug8i7ceS8TU9fxi7XN6nLCD0qLAAebCz/Ft/fo2eZVwzthp5UyLTqnf77wxgNG2P +hihCO/d0/nTPZ6F90dk8bYfN0H1+y6d1ltdUKx196mqXpkMrUofc+AQfT84StgM9 +L7SjBHtN+H9Fy2zZ1PuGZW9r/HevZIpkN5wpqnjyBvsZffszZY0tROPLA6t2NqaJ +E6T7f44WICNUigXghExGag7aG2aEt3oWjlXVif5X5krza5Q0P+32O+bISy2NGGyM +NAqIi/5o6T4YC9FgTOKXODSDzm7M1v6QCKbTCsU0gdB6quQvtKZfAwlAguNq3zX1 +GLl3zu/FPy5pwqPOTVvBTrFJeaVzbPry9tdkGjygFW2MeR+DmbgWULAJsCCHQKIQ +H6TtwM/7e+SYey80Rf0Wc4gmTE72xtgaC/msGkZSYnE5+TjO8R3/p3RzJ1PCrU/f +T1VU0PwzlyqoO4Gui+FYwR81tGIiFrZGvoTT1Th7NtDGtPjUvfHchZujreIrl1a8 +siiRAc439WaOUWVS82l9rGwC7jyrNcQAbKHTFVOzDJFTqQLYWI25UReV8qYoOFsh +v+vEgOa4bh/i5xczG6tj23Nsz9XMuOCUPmPuizGJAj0EEwEKACcFAlVRJ0kCGwMF +CRLP94AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQsmmV4xAlBWgDWg/9HhWo +4WKMZ7axMGJpv6BYxfIkTD+AM/50W9PW569OshBLSqCXK4EL6uFKW4hC3R9R7ecn +TFgdT914Aa8EG4+7pB/5T8p9hGS8lOFh2WI9CRXiW9CyacJvI2t1KEawrZITVY0e +nZ0YFdIhhqY6Fa7LhtNMG3blqoy4Ct2JdmF1DACRzIfoFIxjEM9Xb/LgD4vKn6tA +uQqUXlxS7lBsMUVhUDxXu9mfLEy2wH8tXSVXcP5RRTLZmOTV9s35izX+fcmKHCa+ +wVX04D+kyFQoacfiXbPvxkvmVmCPfiB3rhaCfvhE0Oea/I9Vo2IrUzQ+N9mCPSTX +hCVNtQ6BkdKShp5v2+A7CIr5HX0qS3nKibNBc8SlEPpVxrPhmtLoKI9qMEHT94jg +pGDj6enNExWWi89h/WERsy5ELIbE4DJzbK3tmTIPVQ/8P2Y6D+H5hIfjCkXAF+/E +loYLEzVRhHGHgJOa8tmv2ILxBffcqiBmJomUQXzlmCqsmP4vXDdCoSTw2ot/qJs4 +sSHif3DXLMKm3s28FjMp84AJpRZuXmiteeoB+B39SfTVOrquvjoRLXO4y/TqfhaO +PjJx5JxZHcRIaAY0XqINRJrTMqYlOinjNbR/z0p3097frKnFx9QPl9XEHUPlNUL3 +PiAyQ3vUZDtyNDppvuLqEXMtHob2I4aeCR8ZsfyJAlcEEwEKACoCGwMFCRLP94AF +CwkIBwMFFQoJCAsFFgIDAQACHgECF4AFAlVRJ/kCGQEAIQkQsmmV4xAlBWgWIQTj +/yg5wEiyXAhN6+myaZXjECUFaGTpD/9XXlvKLaRH+5HgbXoQKQBrenOF0DU3Mfzv +kiMEYAyOBGzHDq9p4hziH+gnd/FDuB8SD4GN2KzLLxUsjm5XVoAAql7raE5s+9H9 +C3XO07/4SVZVbjouj3UIHTzYgjJZJrws6Mg8XRt2q+hUJPbNN1gPUC7VrQAPhYdt +YtYXaQqkPMLW77uWIdAhCZThfNw1pfrMnp3fnc1MPP5N2T11ZZnzIdzVYju8rBmJ +vABQiy4UUm7Ux+wMc8PAmkgiyvb8tYnC6Z6d/j1cepnZ6KXsSWYDur+KL8BCAQHG +WfqEGg84Qdw72Dd8LT5421pPKZRJxQseKLz+zkGrS4oCxQJDAnyBSOEfNZqZ+AW5 +ZBm3CKxl4DVInVWAPntpcoXAezVMTY7/AUVNLB9oHd6QnMr0I+GNwUB4yXfywCgX +i9sgaulGhbiO+Q9Wpxc2iqlLEnI5ttzUqyWX1p8iZ3Stn/vqG8KTME8tMkLBHzhd +syC9BOacXoAaV32+VC8g2oPA9TAPIBr+GnvZIHEcPE7Gag0a/HWgUwTjJzctNQXF +HG9X7dWxYUi+PCmgHWKOy3kuFOz+jNxWJkIIzYjcp4CmQ/mcDJqFKeZ5BD0guv99 +h8pGT6ntapS0UO59QLPWgwshfHrJ3Wky2jx1PKqRJe24D2LJpPHHM7Bv0vts9TQJ +QqMRSLNmdIkBTgQQAQgAOBYhBFcWlZWw3cKgNA6ZA+Hq3HzRL5njBQJfV2GeGhSA +AAAAAA0ABHJlbUBnbnVwZy5vcmdBTk5JAAoJEOHq3HzRL5nji0AIAItRQXbECp5s +JC/TP2LDUZN6E2hksidawG3izmDpVaIpLw0+2nCcVfD/M2/KrNZW/Z813PjfLhBg +g9Ar6oB1N6X7UM8sKNO6zt4g9VVziFvN0Rl4osnE6eO0hlYRq0hWsjKmDTnKA3fg +CcNZwdtLhsU4m3f3nP79aJIGzdmnsTzEUckFhxXuG7Yr4YOqS54wkIXQt9XchZIe +aPok6oYT8zDqJP7ChD/wp49ZbAedr29VL/+XvyEOXe8xhmM4N97qIaUdVwkXALnR +9eor/YftUvPlTFVGo3IB8L6xa1mG+6WH+8q53E62CrIGMEnycX7015JwXrz++003 +mP5EyUzLFIiJAhwEEAEKAAYFAlfDYMwACgkQcpayT/HOoi76mRAAhuxCj/CeC0a/ +Y5BnvOFtnB7AvTXA++8uhNDjxOYT8nbj5Y2K8ClRlqi9X0zCf2hYHsRUliGpCEy5 +wzrTjKZj5FU0P/fWrFAhHhnhbMOU+3ZCDvlvvKkXxZ/0wbHbWKLTmSkVuispjqPH +Rdi7lwBO6n6yqt1/q5bTKYF9hT+6WHL05h9SyUMx+vhmgq2+/IlDWq7dVFo0Y5v9 +at24Gk8zUGY2KL85pNn/RCQUXl3DhMxp+//Bp4qaSI9x9lJ+K524JHlq5435CQ/8 +d7XmYyS3E9+A5K/TaRy/DRS6bt3+Um4GMmUS7MV89hbKummLwUf5dHmukWgKnXjI +fxxA3SCRrYH85V99wGqXMPnRox64etnbUFUGG4uPCU5KoXg+o4xTYQ6CxZCu2PFz +0CKRNzHjK4/Xg1dd46mzsUp+WYDD59SNMmTbFmDgyul+ZpbB6agHymdi8bMaKcap +EI11HxPrEOBfWzK179TzUIhHzxx4cwN3QSLcyDXYKYIhOD2fXwp86BZqzdL37t78 +fhHh8KAazLCJL6x+LU8E08qxGWOmqGmaH8yXQwFVBgvZwKb8JXJK7+cxutxBHmD2 +LXJvwJYt1RpL3tOzqYMIM3sigEosAn9kjDPvSCnLczssKo6VuRwUvjfs38SgWERW +kho+QVRKfl+Z+wfHjxtw9VGpNDxEP/i0McWBdWthc3ogTGFuZ2EgKFdvcmsgZS1t +YWlsIGFjY291bnQpIDxhbWJ2QGZiLmNvbT6JAlQEEwEKAD4CGwMFCwkIBwMFFQoJ +CAsFFgIDAQACHgECF4AWIQTj/yg5wEiyXAhN6+myaZXjECUFaAUCYJF1qwUJVjAe +EAAKCRCyaZXjECUFaOX2D/4i7GoGoCvSDelslxAuiQHO1lssrVLnaHRVYMxOMrYs +QK3oPRKNU0rJP9KdyOTL/mcGMf2mzknF/EohcYNMzQeyPCjjWUUrDRmOGVykZZ6X +QB6cRWilDugpIEhMxf7lpE99h5PyYxwS407A/8QkcSVg/Dc2/TfeRT/sjbmpucBo +P7K7vHi5u3DJ2SJiLYoIYfMSPXmsEvBn+CmbWgrfnag2wmC0Ct4PD3mHfx7bQBoA +2m2InGLJGDpZ13FM9I5ZJuEDwja3DYfvMRrFNP8UqTplOKN1T0Ed/tdEVV9cWd8o +i1hzhDINhmDVTMBqHT9THfkgJLt546gvQOdqfHF39/jBaSPkZl7fUZ/v9EiiWaNl +xiEglaFdJ4L0qORCRd0a7oDZF9+rOYZrx3n4EQNIMOXkmOIS+GoMlxmqSX+65YzZ +yICDE+6V3ofW8ZvJqrYhBJdv65vZtDIXAosruD6s2qhzUbWDO9z2lQUUL6E9r/+N +iRThDNITHw+HxYPYLCHwhMaoWFvHL4XY4lzByBLiQO2mUM9Ksai+AL+dYWQaIhj6 +DmkaldbCrNznGUoIwBKXrvv3XCTTBvs0JVLQvPyCGCWjSuKApfOSVeCCUrhli4vi +tYdDuK3+7nqLB6W1jSt3e6aWHSGEiHZIzbWy7i6gl41mxUM/ke6fRLHvoQPh2IA4 +G4kBHAQTAQoABgUCVVKOTAAKCRDyIcXSxGLN+AmtCACxZgrLk2X97nFs7mfubLlU +eBTS+gQ/WchF00sJAdrpckhSFNYCkp+tjm7nxHYy5g2fHc8dJ+ruF+/c68LfeJ5n +fklgrRiDcji9jPv3fCifCIQJfZGqqTYLZui9/UR8cI43e+4nrM4Ubnjcv5QZyJQd +KXUvcbkNI4sYxSxdTLfNRjDTCpF+16lhJkc/FMKcE/T8gqFJDT2tNNL0zEFrPENz +89zn4N39D+J7hCb5EulZQ9kw8GSkygfUOnIHq8VbyGkZg4bGEmMX3xedT7KsxI0e +IIjUViu8oRO6p7WExPO2VeiZxZy6umw0c4gPOaTR3un3eBHagq12G1JgYb69wIEB +iQIcBBMBAgAGBQJVUnObAAoJEJm13gswlmVpXYQQAJvWoKyd/qq3EWaF2CwJjMFE +pN8tDoP7BSlmBnO34M6pr1wdTsNUcA9U0Z80OCUbxkMKyetzL3Vc6ZhtdPBPzWOV +2YcGOP3g4OUaO/y00cHDKudi0ajiIQfLHOhTNwiBqSD0TBex5vfrYga6/TQZtsio +cytjEKwSy3A6g0ZK0IDYAITUFMdLHongt+it9vDUeRZkBdEVbNUVZblLNsSS0/MZ +nxvtlsJ9akpFaBxnaGChy1V4Fw9/EPvVT3fxYPUMo0FJsOoi8NnpUajeZLD+CV6I +I0kAsor0AijkduvnsIFV2NktBZ8Np2F72bqDdUSCTo/TkYv6dyK9lI+jjRd94AyT +EP3YMcqhZYU31rH86Uq5HPQOpfzvItdriL2QbCWk0UEiPk5ijALJPvLWswUYXmdV +f4qBFqD9eJ8fB/ekQSvhIXsSSe9vM/1fcvBRw1TJViOCYW77Z8lC2cuSjddQ28rj +z0RdvKt3gfVeiRos5MZ5jDETxpoGRRAD9qf+p0JOTsJYN+xj04FTbY3vMl948pSi +FTF8MbDiw8IyFTwOv7i6if2StPiS4ccSt0BRtYQnay/bKJ+n8SRlKOuAchCWtlM8 +U0x1lE8GnoKTWv8BozbqKw5OSNETGkKH+63QCo60oXpGDw3e9ORnESFMKDMRCCrR ++m5Xxdjq36ZxTRf/+yd/iQIcBBMBAgAGBQJVUnptAAoJEOD6iBWTWC2RxXAP/3Zg +mmHo1nxaM8emN30NoZWrxD+OM0eHav4Xe99D5jyxBYdgwQy92JPXEYRGzSd2pCi3 +bytDfmmKUiSwYFVcbY4ZqnC1mfaMN8Mty6n6L0NIAy+Ix4cZxWFvJGln6jLk8Jlg +m+BXKvZaclPmOJTrweWrgq2w0UeT8s+NX8+t8BZHnD7oliyBXzCOQEAN6UzBBqSQ +NFEVjs+5fRJ3rmlqVhLe0cwoxnGMlMNUEbxbTRdQK2ZpV5P7tWNl9I5ydSEhW5ws +v4LK+EOGHHRmiUjnxYSpsP2JszNcb+GJA6GPt26CEM7sS+Pl0dvM3inpjnscP6Jh +OQxOF6bczVHX1yT98/Cr6Aksqgycz5JyEvLca93GKVLt2C1lNuJXyaUMLpYzr7jR +APEp0dY4MGG3yO/A/lvdPWbrRJWpT0gBJAD8djrxYeeljaE0jUlYZUadu4XRVbZg +biSNgLnZQUuxe86xwjwCH1t8v6itDXyWroML7anOfl2iPdFywI687xEKaKjbIzPi ++FCcttQzuFVuDR7Y4ojv5X4OL0RU+XlLbdvqNfDTPWRfqGcYQ7jxMLA/JtHjxQNh +6q/vDqvF56Lxaj/YiPdtZb7zDQqybZX0UjEmyziFsn4gDpMyQcG3vu0MLjqwK4/L +MoQowcwhikLDfnpexzx6kFwSm82sJTraI/2BUS2AiQIcBBMBCAAGBQJVUnvFAAoJ +EN61R1ghsLNjsYQP/183jZ0N1z/nYvZYNhejc95IrNPEXvMsI7I8FLZvhCeOk0xO +jmy4nOieUFc5CCIz/khFlKaIadpp57+cAcF1jOTuV7rrMlrud3qZtdF/qYacYrzq +nFe/L/pThNzGvSB2sJRPA50KEc8jVbM0DuCn7NRZrHfHB9W2BXmMt4LTe8ou6eeX +pnST5XUM/Sn47xiOfr74xFqAY3Ef5k1O/6Vue9sQIYLmDUhSUiMVkU8O/9Y/Onhe +aXhmAqrDVkCK3r0JCEYULBxejrfVDMbPsnsS9bPRgKwDxPSrwAh87l3ssDgQa+K/ +2xybuk//0MLrW9nqI6A7zMlZ+z7V7/cc24XGtZYUkJnZq/xsscS1Tq53x8nxE/Jr +UNx+zoRagAhH1902zz+uRLZQR6ObNEy1alIcAJOWD5iodftd+mc31rRhJdqIU/1p +lccgR9+TZOEUlnM6MCI7rBabOOPQrDGWVX9d7NtWUSSv0Eqc/QTnhMnQ9x5xkQJ6 +z1Tiutd1XRe7O1Gfm6LYXG+3fX7oB/obstVCbuAYskipgBbcm1+YaUKUkp7ed4oA +LQfU4s3GfdSwvbawbCOOdbCml1cbsNXtToqHRP3W3TvAk0glgN653LK1rvbnMWED +BAXoyofEHqTKWJkUZ9a4wD3KtRkdpCfhC+eZIJksv11i1mZU0+nNbVUc9bYTiQIc +BBMBCAAGBQJVUn2FAAoJEP9U4S4cphmymTIQANnW277hmIzyosSp1QpwI4ZnjDhB +ssXLE8JaXciG7YV0I4KcgJ9qYgzoXG/epiN87QN08G7is86KN4KCm0gFIAt/kUK+ +2DrWfTSSnjhQVUo+tOsfVZ7Yb8BvB6rxIoNWsXvNPY4o5mWFVNWWNkgHJQK4urRm +JM/Wvd8sJU+zRBzXvao3wTiugCTpecZnS5H30EnGGfete5QbsBa9foha47wOrvoa +lk5SUdlihIGWFqF/DcvUjJQE+r0ShtQk4VrqiYaRPD06pYi6bxcztPpfhiVtSYqu +ULu5uAebxI5FvX750CoGStNLLZuvuQvuEuCPsSuF6BVWEqyLxXiSYAPCLwCtwP0p +sRs+T1dpwP12m9xfY8V4D5bae3aeDDcO8c9RDLEkKgRZnqhdR1o4VpZ5IKZcNrIO +FHpqlDE7QSHezAfP9vOylUndwqZDTu8RQ/jImmAK4se/iJsXYHU2Jc+NwBMsYRHH +yaJGX7fYNdUWICo2yPe8GiM/4pkGqQoru82bAJbRPBBVHQ5JnT0ZI7fqNRjyVFx2 +xyyspBEC4t46h0Kq1uHCQD6+/azZ/RRiyJfgL78iPJpTnd/50OnUv7aDpX7jUqpG +q/dfSXTloWS2fZJO0/0Owq3opTWnpm2BSG5yonc4sKwVM6OEGiORAPCPxkzJhcUi +5R463KR8q1SVuotkiQIcBBMBCAAGBQJVUoQqAAoJEJE/N13mKpcMz3UP/3LoyHa+ +pME/I3xIlM0v+WA7d818QABictBZP4is+hvztG1mUcGCnbYXRF4G3tgeIbkJGL64 +RZ2pHcLu9qyEQOQ7IofzYHSRG1OsFyBspoiIgyRhEsToBB3x12D5RamJ3xTlr82N +gCLpi+kRDNfHIUSSFIhDsIxVNGnTyUXX6Nvb4fwNx4ef+5gQCuazUp5qUoMQPEcA +hFzAgyPPNpSWFD0LlxUxx0kC0KhuXVEE1SjE/9IllNkUPpUD+cA01pv+PTygig6G +HN9HT2IjtRXAyNe+4k/8GMN0uuLwnsXTOaX9m3tchv5X8cvj+f+sFh3vhhQ/erYh +GJtdjC/S5vNAI1/pZe74aET4iVE7djru0KbqmuAabRrbnmrhrsJ3zvl3WGE+CFXv +mAdcMoS9xrjToO+Xjz/qB9KzyYGtbrP7yN+YCiXbclbQqOAzy4tX7TwxBQwevLzG +keGKKmu4dvgszZh8hUX6i1BSGaxpo+8GKQi4iPPVdsnrDHQw9sTl9DEftwMBvH6W +KsHeqOmH+Jl2vIWx9aP1AiAC1O7IICcxwd4bgVAAOzmq99h3JJXqC747ODsa/XO5 +2bjUNxx4UFvVYgQKauLBMdQ/BfMpUIVwm5fQxSFw7xDmwsaolTzqUNwKT3Z/UU6U +ZIS4ULPRgJDVWxRdJ4nJRDF+HmXx8ms3SxN9iQIcBBMBCgAGBQJVUnlvAAoJEKi1 +H16AMszkLJEP/jHyjlzF7zJO1K+6n4WNhoAiSZaTrzKEhKUhBiLEwCR+qB72GEwd +VFMeFoLPkI+Qws89g8B5nORwK7skiE4cX9MPjhSp8AqjwIyTwbi6ux+MTQybvUb+ +h2BsjnRZ4Wrq+sn5II5sO3NgtnVuSE9PcohzMN4wp/P+5zApTeot/FcCWezT+Dzu +i+PkhYDZdDAmRCijSmoNf17aDaHWTIqjC8eSkuoNIRZCMWoOaEmRdTsXRvpePCfO +GqrEXAaB0WyQMb7f/2yRZqbRpBPy8OGNVlAzSLlXxhe6jcrEN16KzpOm8lIpQrgR +xgX31H7PDoTx6x7OKAxeVO6OkDxQS2u6YMpnGiS7BmnGYK161BXIU2VczPrhIsAM +uyxhRywZLD/uBjJh3a8qanNmXoleJSZ0kcjpGs3usNzCflJECN6d7IfoVIyWdaE9 +uUYwOaYdGFO8MoyQV+iSzVSNukurud2iC+z1FOmbHh4TsJaPQqZ5iAC2bLRXnS69 +3hPMZKMgJKxg0ah/RB52TQaOmyVtGEngkENayCZUFV4xvHTmhSmYbvwS7OSppoj+ +tu22v7EzhX558DgyMcXo3zpHbMSFcSQ36Ba5D+ub1i4oF1/WDmSplqq+SfsRzZL1 +1+UHrmPWV/j7JwQgosptc6OQ1AV6uUDwOvh5whkjki2ec2X+/aG6vnZSiQIcBBMB +CgAGBQJVUoRoAAoJEK3dQuDpdK2PCj4P/2bkpd/0GpDqgtzfDG/rpuwz4spnaKwE +8yzpAiJp2FMle4dziypqzAbTqk1Zag9Hb/1BpnAQ16/G2n+9q/f0nd1OpzPIZoPu +tuocAyurshCAddYp6V6u96pH434zI8qwTYS9hPlUHdAqUjXsmRf3ThnDXwm9emAx +DiKoABR8fOf7Z326q0kJ5k7oGTnlbcNJ11VxRDr/Isirbg3q2jNZ+x0NirNJL3lm +T/3xsP4jO1o4BoC3p/fEkA+KYXSUM6ch4xvxdQG3svstUtvShfYl9sPCAiJ1+bde ++JS1VNP+86DytjU5l3KO4kXjDi5stC5j4al4Yctor3U3fmmwK/KP4X1zcNEalSEz +H7CQNbhznCUrCPfrewuy8rNesu3+ioT9WfQeNI2MNSAj4seavgyDGCM8WITVG6Wz +j8I/F9R1rItf8ZzJWMFn9okcz4j04spvr0R1kLFjApZFhgJbs723OAFnePPn2Or1 +iLcGeENoyn9YAgg1M7k0bUJSQXSqcpI6huX00vzdUszxFMTSUgCxWajIUF53ZLPf +cUuiuM/W2HBqxX89dEbFdtIynayr0DmV+E6bCZpcB0nLUXH4yXZomGqd4gNcrFej +zDxjPkyonRYo9MjsXNKlhMdqfLdTt6ywhLrn1DTDesgOobGTNkdOiOcjOsqbHk5g +Lf7TWNvfvneQiQIiBBMBCgAMBQJVUnR/BYMHhh+AAAoJEPyfteEhTukrH4UP/R7a +/Vw3i6Z2hcAxrtUzkYZpXRlrvTf2rjSBq+d+HPN7wNq3zvALvND67j6wAVYMXEEk +C19l+ZLapIqR5Xuf8q0fwSx3UcoAsa90pbWDyqamxx/AP4HKFhoamEY8oNMZkD1x +H8BRq2Vr72J8U1Bz9SXl9HIKvNdy1du1obS+0ORdcgpB148IhEeefSnGIIgRhIJF +VvBDsoq0lc3TSdBvHvqP+Mwwh68wQmILuu67XkKRkJettn7W5HocoCxc4adS1WbC +ZToPprW98RHEUACk7RhVxel1md/EuecNmh9JM4FT1dppAerk/ad6PDN2nG/KINd4 +bJ8fXij5X9hs9JsSGTnYFAJRa4JptDjAb4aks5BfmXLpbeneT8KQt9mlDXifDKOY +bx2PsmlqDoF4wI/gJRzxJ1/5yL3BOQkbcUe8js/aINJGKyySXRAe4qqg3HqiqCWO +pU9DkJsEY5BCI8cIrxSMjqqkZ5LJIktHNcezuSKeWpyqQgKn57ivQAHsLanAOdnD +iWycdAOQ2A64b4EznMCbDjGHbssacYI70R9JYrM8Plx7OHn+QUTEDJztd5TU18u8 +K2ouEOGLJRMmn0of+stE5HIw5r2ecqIr+XVqV0M84yEdwnLBA/fsWZbA9vnMWwr6 +QlZlCCDMcjS6cx/C/M0tDCUl2rKhpkgaTZ/d/I7LiQIcBBMBCgAGBQJVUq89AAoJ +EOCV2+anxaJm5gYP/1zrO8ozHabypD8wB+jsKLYUkWEaN+dijTNsLvddGWu2LF7N +G4rh8zsiHG/FuhwOjfm+5zAQ6Uybl5jxi8wUyc4XhajbFA6Zc6fp/xn0mD+TnQLN +aqBoMWwO/vzyYBmM/DwQ8bsss0j6k5jbUMX6CoCryB7B5X1iAlRr+5EWr3NDgtt0 +8qtufIL9dYVBFG0ck8IR0jvTRxEFdGXaywgBYtWx/mlfn42J5FRXjNhF3vYVQg7F +E/iHs6s8OdlNju4kllC9zt5Jti33MP9yoITXkSnymvMr2qZOMIz0TxbmhKW7RH6/ +hscjLMvz4IhLysniK47a9UrD86zd98Q1Sqjst8m8jAiZXnPECQkKbsIlIqhhCRwd +oXrA5zZ6QD4XmLnTj3L7rEYuElUly6SDZEnhNS1T+JX/X12LWBxjeRxPSMQRyoM2 +Fdykb0RmCq278hKkJyqMKZQXbyhdjDTePnF2rujV9wywtsVD0wHc9bD2qqGWjzPM +yj9HXPhz+fKpC1dXfM9aRDZCGa4gWvr4NjjX8sjV9o8FY+mDhqN1dyS8v1WaBsXZ +mr6u3HZuj6EGjyWVmrfWE2zMKdjonAJaLy5eQhq8uio/69M0nXGSv3hAqN5t0UD/ +pgoYgm3APwf9h1USVRsYuGr+IJWg9PiB1A6DJ7/3Geik0MBPykQ+hz5LINhoiQIc +BBMBCgAGBQJVU3tYAAoJEHWlUacilewfdpgQAKHzOHF8jc2NQk7rqtEvjxbixa4o +zbamXbvrqMzjqTm3gg/h8b5npiqdFJij1IW7V1nPIyS3ZeYHd9EdoVwAR39GhQ2T +ET8GAai+fjbsnDEvbITwOLoSZkOrpgGs+rbq5plvPYy2S/Ca8ZJPpBi0gJL1wvo0 +ulztlp5ZbhyvGk8rQL1K9oJkxqCgel82MWRjNM1Pzf7ErD0NUDkBRQocz21n1J6/ +QvTq0ws7d9Nl7TQWkQ61Fw8EDlHkY+wrAJ2rE6ikR6Npd2spLEzFroxhkytejl8Q +Ewe9Z+okL1KOC3HoEKWNMaGlYisI3d+Nr9jTYRYr6kNrWYNTqZUfm6soqMuSaEeW +EuS0RVFCLK32wOFf/mFQiI3ZaetjApPxdOag6CbgKvF3v+2dzVhsOOc58z+7wcb9 ++hJYiyAxZRaNA6wv/rh/Ug35bj80oK8SNqUxHbN+AdK/1A6ZDD6VWIUrWKZH5LnS +rS476agy1miCrqbGG1xcrS+Kw72ByZskF90B84lgeoPNtzW75ut/+HFVvlgmsyDr +C+N31vMPGQcf54Z9mtvJC3ruSk6tHtUx9HHGasyatMfqP1NjsEDq2N8ovYIonCCJ +qpY77qZ7p7XYC2UXmzc85ZocucUMLkAh0fdzTXT+7tHDBhV6TPLHlqFSThbIeV6n +r4tgtmbVV0YOji0uiQEcBBMBCgAGBQJVU4upAAoJEL0AzR68SXz9cxcH/3XynlSA +hXm6iLZ1nE4ynwSBO59ecAfVJyd3P0SNecl5V7g/rtw11e9WzDOQlGpAn7l25P4n +khcsnZyFBb5euFgFJ3rRp7ZwSO210SAd6AspNSYbVRWBwGbbZEYfNGoK4cwMJg/i ++lWq9J9BpcgnW7ZBBjTm5SLEtY6GxOJ1cyXRRfk6RT/+bmdQxA7BUp6GW3qaNGKA +Upf7ozH9TRiKHrkv9qBkF6jBToW3SNTP20Cqsc20/PnICUTNWAppK7C9fKn9Kd+k +3u2jZQ43TXSBGDN6++cU47Izx7F8sSlqtcywUkCUO/diZYe5fSIy0dFHS7wo8+wj +9UpnRJveyR5bOAqJARwEEwECAAYFAlVUBzoACgkQmUUzfyiIPsuMsQf/dHd4Cmqn +wHPGrBawyFbcMZSn0CnlaC3pUJof8fBpBu3Og0A84YcX9Zoh9VRSyVZl4bBtcyk8 +GM3p21bTII1bi604KM8KTH7wcubRvFbSsz1QdCPxTI3RfuJ4m8HWxm3yzHrYPfcl +tvMVmdylqOE15Y35o6jZrxFE6+UgWnhz29xTOri8Ec4uPnlvRsSrySooi5CohYkl +SuQzVLY4CJNEs5N7ktw4QDtmNZgzHtpQuRuZAIT0zEW+h988mhu5UNO4Inj6nPuS +/+3fMrnZYtebJGWX60i+csR0NlQ642EMfZN6ZWaRRmTkG4v9oVXzECjRhvmneC2u +CVKdl8TH0fjbsokCHAQTAQIABgUCVVOi0gAKCRCCQz41h7KufeNID/95ZZNV/1Sk +PUAQ7REQ4CH9w3bCmi1fWUYcXaj3GRjHPUfoMWErxnIKHR7JbiL4aVNNpXvvKpDZ +1H1TuBMCmfPoQ/ZyzfYHiLt8KDInqJmM+98IafwRcnFVdWz72fwSWlB6Syp3VE8M +Vk7JvgLUjft6jWfxp/isygSagkyHGgP6tHw1SZDUU+RffryfWam/N1pw0NTYdffJ +HeYVl8x5dI9PI4owNf/qHizVb/b1TEtBfzMDbc9B2lMVvK7IBD6MTsPW9Z/PVF25 +DkKMegRN3QJXGzgpmj1bQvC2mpv7+LiPRY8WeiKlobvlI1VtNNHkCyPxnarCRH0y +zcpS009UFEzDQAlSu3Q/DE2z1+lXEDzcQ0n8TDASfDSdpcm/Zxh8j9ainFtrj3Wb +M7KHwoaGJsy/o8+WxBDBl3FIJZdCG9toaXL47XHfwNaN+k2ICk1zinFuutDk+/Pk +g4kFDxQvNWYCTXz+YhIVwKqF5QDO7Dmm9f7tM0PGOr3fUzEYLm4nTB1oKpg6rdxD +QGmCXzlCMiGZdmUPlngn439KBInsKTwah8RtNVQVWcV6t9P6gBPCCH9Sb/wcNcft +287zKv7Hg1Ezt2ceKKvQtGNs3k0NBdco4dyimJefBlWMu5E9H2MxLcuE0SAWeRXA +zJCbuGIF3BAECz2I1d68me3yhzshXgMG9okCHAQTAQIABgUCVVVFXQAKCRDalBBI +g4QoJp5ZEACYmWwPcCc6Zv/saPXJsiEfXl85/yzS5Py3+J/YD1u2hpVGirv/Hmy+ +j83SrTOSaDNCU+Nzqxnqpu3VFT4n53KIp0Z0k2LYefSBqqWd3LU9Csezx4NMaYS6 +F8Z5JO8Y3oenG6TUjmPuaKe77THAPf9i99I2RBly37zkv2LvfAp78XD0MyusyeJS +eHqXT44xyq4TF/b/J3PBZJBlyxqFEi3F5pRHO6RyVBAWMEYZD0K44/EIVB4VAbkE +vDHMn9yyMgdRkLbeuQUtxsG2RBa8xflpPuHDTtIKmCnhAfUkEp4szy2xqUy2fLNf +8410YNCTJsg7OtFEZNNA+H/KJTQJ0oTSUBTlNEWbe/v0tvxIrhDGyUwkYetdSUkJ +qF8NyY9kfwyp2lqz5cEm0Io9M81djkNXTlen4nkZzscUIuUXH9jGSWwiQxROmS65 +Qz3JZ/ciVjg14CEY5LCfD+6/COJ0B4XSK3+hwJv6XnSHUInyWqzKEvamp9n6jSUy +buB5ooBQt++zCxfWiNq9s/yjPive2/bPbWHFaLAC3Z+frC15uzCOK0Fk4K6WRp28 +QvaoQC79Ycj/qSEurPMBmYoPnzqfaUP6z+h1KF97uPqjgF8m2ldRNVWX5yK+ocQr +9Fxf4wgDduD/JOTozsQgS8X62oDNG6dC7A259IIUWsgTSY9sNyJIs4kCHAQTAQIA +BgUCVVWO4QAKCRDUT8vOzklurrA/D/0YLssMLcu0LfTS1NBp5Y7ds8UByA2rc9Zl +js37909upKQwveZ/gxcGvsOkhlfhq1PClDjnss3kX1tS9LevKxavUOuq1OpAwaqD +KtJfRv3c5dyXGVrwfaWDhMruodCWTzoD8GlDyK8ED0MD4uAD1jjat1w4WbQSXwaD +YKqNvFHcRH8gqvXwG9EDgbxl44YC4nFbJR7XeMYGUeFSKlJC+dDoJuyjSCB0cMQr +5jYbgRHvMCG51KROF23CnjcqDf9jKO5btQUl81REwC6MdrtXiRLixn5MNNXgnQld +R47TZwNOVjHwx2fOdHZlb8oAlAX5JJay0uQF3yDYbY7cDEZlSxLfbRbb93H+mbYE +nOiRx59QABiO2Upu3z3bHJQbxie8gkOQuxGENkflHz70rAxKXtNVMaRUVmUnMABU +NhNtRK9m6R+cbksDGqqMdLFvWFtUikGVtmG7EVcxICeIkNrSygtJoUNpjFw6OcB6 +TNi8XKBQsYR7BjVS/HnXPIFG009rCTboFg3y3mZwQxHGuiX29d1g1KrcVbPOtKPo +bPOXA10jjR6fKDkZPRxArrsbNOPrGeMRejELZw931IySQtduWg625AxQ+1kxA4+Y +yHqh/5JTGBdDrVtjFEwYVeNPv5XRGIGn9hGUXP15L96KPElmD6vgZB/L+OKHoaLx +eUBpViy3nIkCHAQTAQIABgUCVVY7ewAKCRCi4qJtRTqL/bmUEACa4nqufTzkFhP/ +CUw/TYX18L27a8GQvuLWVNbQEdBV3/ACrT2QEnbRfuX2N5yY6hiwd0Z6doklEljn +thX3I22BXhmO00y5A+TP78vTAhNlZwHmT+Z0dUDW5GAn7WOF+rPs4aFIM890i4Y1 +4QmWybmcFv3UqHE2K9KHR3qsHtaBo0VPBlFdQW6YOkupixqFIrsox3KlM1BBYJ3P +X7gtvOVcdHPr1FOKyQqlUhAgDWljtHm+mJyY5MeYuLNgfsp9kdDwbyW06QkwNTJo +5GC7mz+iVurXOmqNR9oHqywnWohE6/LvFFYD4Ab0EIfkd/rBnR1icB/u25L4gHi9 +v29oqzixk+wlxfL+nXlDsg6khjO9vH5JSJdaxJtp3q7Intnr2WdeWyhBebQLOSqK +yo3YYe05g2wcc+uRkMXyJZZQT29iaGd7d8yBwOqdO5NvmYJxiPmTjlaglzeIakyV +83aPep2OzLOUNwJlQesVt2ewxjPsjyaah3ny8OQMN/iTbLoeQV9en2AtlSiKsgEr +QcxneN1iRunDtjT6HAFgCAc34zucFxHrvK/aOLUJewIbcKz43I4rcVVSx8wb35Zs +UDcbAVRoLfeOjgZTbaFGmjuj5y+Ums3GbnhqxtvOoERtknhQLQUQppgsNh+Sym1L +G1x0CzBNPO20uZpPqJ+FBEQ6GiGtyokCHAQTAQIABgUCVVZ9LgAKCRBY4Rux5BTZ +ra3mD/9m0BnXNbZgkMLIWyw3F/8XOeaSAZH0jQQv6pPO/ZtuEjBF5gs5p+b6NbxE +prv7hFudjjqPwvD3kbc7ZI3DXfCEG6T48bhALmxwk4BY84LwYwYAOLagOyHRksqc +Uhh+3SeH4T35LJttYwZCqDSjnlCvUJ8LaFa/MKqQXkYSVCeeB+XoGtIYW7yQD6D/ +ylTcQTXRVuFhdN17D0oermlrrXeQRyeZ8WZ5wa5mu8gD0eHlnGd+eU2TegMF8Xgm +qD/FBAaOssX0FHtYlJLhh/w0n/jdT0l4Zr7fPU+DNRstZw8ybhSpqGcNy+o0j7nA +lC2KUGWP9A6e/muafKUYuXL+NzF0OCgSbDNcZIGbk35wcCYB63O6HMuPy6yTj8gg +O5g1nhQh5AtbgjDsl6Js/HCrAYPKVaWK8RVLxFIZCZ+mTVlT1YSALnI8+IKQELr4 +CrefXmdOb26lY6T5fkWxyfJkz34yhMoYNNgz9fUXZkFbrG/vDBhT4Ec464iWAogF +iKblFVlzUH8J5UwYcUDpKGcxQ1ZBmAIIAHqKi8sQYjAkbLBr5iLVkr3xhUN3YNf+ +OKGPOnms1H2Y1LliJ/U9LJaH2yIWpe5y4V8PKyv2bM/gWtj4rMnMxfuB4Pe2VV90 +oCWTN1ZQmUqxp2GuPePZnKqdqgdrVzl78r2ic6Jq5i7SSR+6U4kCHAQTAQoABgUC +VVPCSgAKCRBP8I+qGGAA1N5nD/wMwwe0Dz3KhKl6SymPDkFvC0G280uxnKwuwfd1 +a9px30gyZ0x12wldFcIRq+IiE2wt3PLuqOoHNGQ3yPrF8NRVyQkJ6J5p5QLEnq9+ +qMrx28mQ7OqaN+w3K8X0ZjVYu87aEuA1zWDSVwNd4qggc1YAa0yAfBgb+uKUgKen +6mrq1W0+syV/G4y/zvCqUUECSOw86cFrcPcJXU9S1S+A/84f+LoC/p32BT4rN11b +iD0CFxXL6QJ3X8s8rQksDz6sBx/IjLHcJofXsc0StC2jhfdlKsWFZAyQABV7Lp9X +uS+Blk3VcNvUjEIFoC3a7LvgP0asVZyu6nk6MP/ADCjiJEFTaTgCBp1615zzhqng +10/NM7NZA88M2CG1vlqNRT+BU4cJ91x0nif6gt/jTZkMzDMPSPR0h29qvgnKisJx +Rm9FzlY331Xua2zdl6kh4fYsJzQnHDSE7ZZx5EgD1ynA97kzPN36O/wkUOIWzhtj +zwZUCixFWKk8hjYfNsdqvnRPccnJQG339MG46T8UDY+0+tVq1e3Xva/00uTM26+d +7DHhkxs1d0hst2DFFN9fp4iFiKGg7YPgHQLJ4PyKcfODVNq+D/KjJYLO2XYMiTxd +DwhTRVe6nPJzXvwrJeaZTXGNh4nZOTZoS9VWQ2ys3YZlJz7SJIAdcW6x5VIRs8Ec +Ua4MtIkCHAQTAQoABgUCVVbRGgAKCRB/2fzLAAvu7kW4D/9p4KbFMEVv6b46sZLF +OaEDJ30LiwFSRSLMIqd3/DNSELjR00+np65sAHgxWINWcTuQ1MOZZ7Y6ky8VCNqS +rlVNXlQxDEWdAxFgttvja8ASN4W6CT1zeF3bCVub8JmJGfeiNnOquAv2vOrwpOdq +4j6s/GDQ+zmNaYlCb5w6FVZ/XFQOf0PKL8qUx/9r4X5sdtP7xgTr/OcUJIzmkC5O +lte08CpMOBO6JXLZNY1GtSrjQ9dbF/PvL2EZ86kSv8j6lcNCnuJrfARNHmR5EjdL +CHWHYPbS0NnvKyhFc9y+ibq3EA9sOkA4cMqdOmBxW4MlIf1MKxE9wTGMgoF0wk3B +rSgI9Ce7uSSdymIc3Lryozo43oorUFpGYbMUhBLdep8xDh5JLwWkXwpfQUfa2Fin +MnPvgvBiJ0oJQn1ymCith5Kj4FenYPuZsdLgAgOVvEfmlXteYvdP2KLpq6T+SBfF +pe7gCQ4NMixjqB0Up6NH1bir5iVTBSJCYm4oqqsD5Jc/Krcq9kpoU76gEfriU016 +Ub7UcdlJXKTZNAK2jsG3+KH8nDe5qkMASBWnYtp/V49xkLYM5714yw0ch4c9gQ+T +q/hPfVYJcjCug0gEybXH+To+gHJ2I5EdZ/JuF4nVTUeZRT9jZ+dSic+BhJU9vxsn +zgnMb5ktwRGpIgBNA+8kce43YokBTgQQAQgAOBYhBFcWlZWw3cKgNA6ZA+Hq3HzR +L5njBQJfV2GeGhSAAAAAAA0ABHJlbUBnbnVwZy5vcmdBTk5JAAoJEOHq3HzRL5nj +gCcH/RRhFHoTnzDtwjY5rpTRA7y15s5SlS4sa5jUCnkEa71oVZNdomF5q9E1EPGL +fqkjM8xQRYCv0MbrNA4j7O2+8NWIsDZayNibA9dDfD5bbUgHgvnl0myr4sajZwm0 +Hc3xEsbYUvOaH+QTQjYuTekZNcmZNIJhLyhgae2hcii5Me5TMBOU9ids0r4p5ICK +Da8l8qb7UwiojaObmsIp4LkUmXB/Q7Eln8Wv1xsdNrWnk2XcA56AkDxGQS0NDoy8 +/xXr5JBN8+5r2p0RRNhCl1ACMJPbZBYf44qFxr/iSDt1iw3DnCQTf+Mm4fJKUK+8 +ACJlJ8ZM22H2T7f2jeJC3GUiupeJAhwEEAEKAAYFAlfDYNEACgkQcpayT/HOoi64 +pA//W7r8vheC8242JABkhxVORU5SQdNKwLay/Uj25bN+rrqgSmzMUcOuIY0yM0RQ +erV0UQU3BmOd/HlQle4spuIJOJwmtYGG3lQOP3JVg1yLwqNv9vrpgEdnz3hOJipf +QnooftGe6R4RI6+wS49dyfGZRQxgmRRw6GVKzDedahZJueSnCjxaXrgnKfqIcGZB +qmDMUXE3Cdc1dLOfBZLp/v6Rx3/eS704ZE/wLWm36arBMbs+OYz8LNZZTy+du43s ++UQH9jNC8FkEV71gMaOhslC0d0XuCdgOffL2ACIkxHJoKtmfXWGJ98QLKcYHHLP6 +q4cDTXJ4vaSUR7cUD5IGeSOcVcI7EGse+qpn0EbWW3vn43XeTh5pACYAB3Vmz4ij +M4qqafdn1cMPNEiPk7ltNsSk6l7QJpoGBlmZ4BSai0UAOxkPxwfpXJvK2VASzz8b +tpWxOiuhSwqcAKmnolZATKvpKv+MsiFdAW4tcOBdHdkhbQ2NMpemb522aYpAt8Rc +zp5OACiQ0c47+muNs1UV228/fECHO3S290AGEq4CmxzF6i6UaLt/KsDazFo65H4B +hrbjqi7LIkCL7rzVYoFSsz+MGdMgiIPbaktg6XiwxZdDfGMPbA/QV4wzKmdTLFYW +/MuB58eu9z1hOXYsbEiXHsXvc1qIG81BUjoFVMmGqUcfVEKJAj0EEwEKACcFAlVR +J/gCGwMFCRLP94AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQsmmV4xAlBWib +chAAj5YtzBclKACs0owhglt7eVds7EKmMfMS9T1gT0B/gb7h6or4tfgYrLdQSClJ +nI4g1OR+Nt0UuTSvRLTqwBhSYW0IN9ZkGvumP/W++T27w8l/zij4H+1eRRvPbVDw +VGYN+VWzUutOKOBqnzEvBOpGE1a+g1HY0QwIa4/9fTjtJo8rBrTFsFMT3P9nNwh3 +tzIltiWAVcDYv8do/Zf5wAytfDg1F2uV6hJr5BClmC/K39ny05cmYFeFz7uX86wq +DiRdZ81H/2jkbQr0vwk1+ttELVGLrqc2JquvKmbbe4eFQz7pLk4d/A/PASLgJQQX +J+zxDqUddGbwd+6KEt+Oj3rAeHplvfO6ljSc0CvDYs3Sti9/llnp9KyxyJ1EjOBP +my0PyGfHMveZhy1Cr/q2EPP7eRkNV/5aUxVrkkUzRlcivJpg/B2Tn6uCAI8oH/yv +/m89ryZxgsEgeu4uGSNAunZWPhoCGbX8k9h0ksqYQutlezw6e8Y95xJI43dSyVdq +85TnYdXRoSbejS0Ra60z1CaAZEAPZl5iE+EUjM63BWtWptvcybGqt8vk0daa6Ps3 +YpXCd3p6MN8Ko0pwM5wSigcPc8nS4D4gpYMZXvlL7w6lnso6ch78TfjsJzX1qi76 +dOKrOblsXKG8l4T7HPRvvBuFCUTv5KsMGrhsuk3T1xtA1e/R/wAAX7X/AABfsAEQ +AAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAIBAQEBAQIB +AQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYHBwkIBwcJBwYGCAsICQoKCwsLBggM +DAsKDAkKCwr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoK +CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wgARCAEAAQADARIAAhEBAxEB +/8QAHgAAAAYDAQEAAAAAAAAAAAAAAwQFBgcIAQIJAAr/2gAIAQEAAAAA6t7KPASh +d1LbCp5oYc2UMn9NdhjhVrphdXbHKKdPr1S81+2WflBTbsWDDyreVj5gkcG9r4zh +joQrndfLmoX2yvIOvGMfIvNVnbHaGVkUwEvglTwoBg+Cxiiy6DdN+dP0y9Awq27M +v5WLETfZDYZbNH1IQIQYMBQ1KNsB5yAk1k5696elAdaNq2/PVN9kJZwtinTZ0wYz +omhqngsCqj/a8QUp6D9ogKx5pdw3tBak8mqJpdUTxccTYuKoCapZVyPjdGobJf0G +AVh2pfw5txakgiCnDeTywpHjIRTKaibF16Qn4sc5VP6LQavZr78/N1pkJNBtwwOn +EZIsPLmUmL44YTcSEMa3N1njR1292i1XfVS4qW+lFtVLrUplIuWZgmy4y6lwmkRn +EjqswdjO1dxqXw59BcnVgrZzxhaapvgOCLEPKB46iRff1sFebGYyefpiVrK9Hswv +I1E3R2UftYefvN17yPYqLN2DRxFj2TNnxYi00/QtziZsETdOd0r4NPeij+7CvGr9 +UOa7qTbOpTeqVWe1lT7ZwV51dCnrU2t8iQbeFju+9r2XKfzz0zPVhYvKKBXrbkD0 +OIqMUZ8ULD4uUqwaxF+ZLJkGI5pSf9cZ26CaVjUeTdSZAtbsdbjYRCEapSm4LMLE +UKBR+uoDRwyBLFbbJXTzWQaldEnVOguqjlLabYJIrhlBaRQlbc+4XE5nK+IXtPZT +es2WhziZUxjePiopIVgNV5PwsuH9fDP19qLnVGfddfHrTqbqHWZ3nSOxNUFKQe25 +qkDQ+3XuOfVXs7HI3lC6Xh605yhc9SrjBDHCVNasSu5novrLDISKbdTxXBD1rTwg +9a8eGV6ZQ/nYE8oJUDkh7iTlF8Np0oSCsrZ7Mnz3gUzWvOdxojpwqhYVwWKlRFAt +pl6J5ueEjTCsqRtGs2+dhRq3+38KJy/eBdU0YUaiRXGMrxYXliaHnY2XnCXS7i6b +jDVx97IyhztbxxyIFcY2fCGtI7Zl4miJNv7guAB8znvsKNXXXPhDMK0uGWk6q0mx +i2CsnvpEaC9IzzvILtY9xZGHErt72fDKPLo0XErw6kBSfC2ZNudyQ/LdlDjgs6AI +MOLXPfONhVLnCjlfVMfEoSJDNaJgvM6yzGd8nnpBsKGKKKNXEXfbGyjQuH1AgwWn +IDzgCpM0XId74Ju156q94i24ww9b9xs7CNfmfuhq7Xb46u2o3dkpSq7yb4GI887w +dagBhDFdNtRdzNVqBTkyWynJ+iL4cQ9aUcRTQ1HjBPHdq3JcwarpoIJunVY5SXjK +RmmNxQSGebYr4uqGsJJmPeJdj+ofX1zmR68YxuahGsNB7FyEisNI9FNfHpG06X+0 +Zb2bUCcoLfdCb43dDHr57G7WiSvcGVNvC6GyjNV3qK4oKKIhoxxkVg5/dCLS3D6H +ubev2PDV2UKYPTlDdWaBRkIvl6LoKA10ptRDVis/Qa70jXHtV7//xAAUAQEAAAAA +AAAAAAAAAAAAAAAA/9oACAECEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAA +AAAAAAAAAAAAAAAA/9oACAEDEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/xAAyEAABAwMD +AwIFAwUBAQEAAAACAQMEAAUSBhETBxQhIjEQFSMyQQgWYSAkQlFxMyUn/9oACAEB +AAEIAvNJUdN1r9U+pgvGv49gZt7YkeBaXiowY5KSoygIKDipJ96Jyiu6IKLjuiBx +lttXbClGzkm1YmI7kDbm3gyMVWkQy3VRRNhQ1FtSVU4VUd6INt6fQULGv8t6x49h +BhEdTYtV2ru7SpLe4XCZqP6f9QP6a6rW0aNEx9Pw38Ui+ajkjf1T19Mi3jqLebnA +tbPcuY1YGWmGhcVA5fBluiLWCu7Nk0BIi8Y+S46ER38tiCFTjfilEgRERpBQMqwE +/qU7sgVgLaeEZaBOReNR2pwR9qlKC+lUUi9K44r4iNJvnU2LzwlEtZ2ImZJkjhP2 +58J0bSd1W/aYhXglrzXmk/1VwIAtMg3Ibvckc07CyjeLz9sc4UbAo4oW1OIri4U3 +mqb02i440KL703ntjSNPq+RVt5THES8i3zJuh+XSVEw5B3oWtxyFBNFFA8p4VVbJ +NlkCG6mDQKqoQNRHHCUyjxCZPGnc9vTrKIBt9wl6gusuK2X6V5Vxl9GoCzy9/h+K +8b71rBePR1zfq1Rh7ZpatAKRci2lFfltkLSYpknnJSR19qCyUiQH4pEEPuBf8VaF +UBMkQEBaVNvLbgqjlApL5QlH7ibTz9NXMEyTkAlo1Rd0ohIFyNscjzCKC+yxgFNk +cPFzLK+x0PMa1JFRozZr9JD3J0fYZUk+Ke9dcJgwekV6cchRhGMS0xCR5kESysdu +iCKNKre1CJou1Yb+aRcV8h5ptNlxT1mngycaFEFoM/NFg0WVKaY4iu22KhuqqqNs +q2Itlxtr93o32QwFCRK4QL0lDFW3OEtsfNdsqGZBqFsYe51q+yttmtzX9G9yeS33 +7Trxe9e9fjyNfqRX/wDHp27De7fFVrxV0Y5wIgMMbr9ux1yEAJgpqfkWkUyVK38p +vtslb7+EQTH00Svf4qP4QQTDanNkpBQfNZIopvv7KhtbJnSC2e+OxDsZR319qaLO +hA+TzKtaXSG9Gf1C47FJQL9I8uDG17drZJLz8Pah81+o6McnpLM2gkXKRDoxtZM4 +zothVEpwx4+RHCP0iIZ/kZTI7BRyXE3pJjjfh0p6eDabmGieFfRFUkHJS5Bw380a +tp9auZGVwJJ4I72tOz40VcXVltFuajJFkd1K8MM7K53IIPIzapYP/SpFXPEIf2Ch +9Tofb3onl/TJGRepmSl8U2966xwXrh0yucZu1q0wypNaBabYZJpZDuxpse/CSUjz +TxYt3/UcGwM4UusZsn/2XWbnknnNX4O4QXdaXAfFQdR4YySG6MOcTjTLpGGVC5y7 +CrjvEqVdrmKKLFJqIp3G+zMvDr1zAFmarkgZrSa0kOJxKd6vMps+C061m2uRxuWP +W1vmuArVvkNy2eZtCwUduqzaNEjQ/pv7Rm/d/LL4b0441FYOVJvfUeHPt8q2i32y +XN9uLodFxdxmNrui1cBMQInb1rgmlW3WpSmy3iUY0CZLAliS7Fqw/LTsW6svE3Oi +zXVJEbs1zFVUCsdx7e4tWiTp+ciwilufME5NivMooULv6uYsTm/7SDGkSMlGVaLw +qcjn7M1vKYzGD0z1+Rt9hbOleuzDeXdOmt7fd4xuOiLi21/c9Jpt0BHLPMEt3Nk6 +xI61ximgbAd15FHRRyy02w3NpK6q30bRa2Ii2fVUa9EsCTq+2sWq8sOtdPyVWyZq +Q0SIQuat7ieiW1q26Hjyd5AW7TUdpoWnXjtFtZ5ZzvUrTsc+C1T+oF0f8srqxXH8 +pdpLStwkK7DYs4tuKBW2QHpQRYSTOXezwRmW84UwdI9kg9rqe+WDQ9sRbhdOoOsN +QOCMCHJ126RbwdQ9R7T6ImmetNybkjD1Za51su0cZcWRZoM00pLGzbbmXastY/d1 +4c/+cAg0n7V0bCtDGk2Rj6ahgND77117EuWGVW5hJE1lutfgs/R6XROnTgk2Zty8 +cfM61x3k+pBBIjOBam1K3aYiuN3gmkEbrq64XG8x7ezPbYl3M5TmGnYOprz3LUXi +alf3cf5sQMC6Olb2j/0ChK2RipMixHY9My8NNnIfLULn7iuq3m43TT1wb0o9qMYs +YHr5Fjr0y0mGp9Zha52o0ldOr+3A1BpZxyyzxftLJg9GVXHHX3PS6wqu7KfXqGUy +2iwGv4Mhu9W4y01v+3IOSUK+a61W/u9OxZiaNt3Ndtz1pdrRHbc0tXTJ1wYjTKyA +TbasfPqebFBV0dVXIY7ZSEjWW6szhvE+4OW3UdhCK5Zyn2TUCPHoeRb9B2Vxhu8l +NuT6OuswH3opnJ04KszGyS3uNiAkZS07MmEciPXJXd37XfO4SXdYku5JFW2Ps6Q1 +HBnsztOWu53DTb8u6adPQ931HcCuV/0xoyVpOYZ2q23R91kQebLMt6bbMCVU6uRX +n+xYTVJhcbNHtyw2O0hMxaSvztWsbd830pMijpkOA5+OrGnHnuU+m6khkSmiq6uS +r9yG8z9GnrSAmp0Vuir4X5HD7sna+UyGxJqriYtiTdGw+8qbJDJpO3Gyw0SeCKyw +ogihIjPD6qQn4rp8ZRTRVzjwWt0F2BY7Y8uI26wWKFFzJyQwgLHiuI4S+YCYUwfq +HaMI4oVa6FS1JbefTUWNeNQRWWyWk+DKoq4ldbUti1VMtNahRwHFB7SrDtpcZoF5 +fJCGxelBBBJCfhLtT9tRfNfLXQ8DKtzo+CetwNnuDVu28vdk245vVsj8cnOozaCG +KF4FBckxm2rm5XylJK5tNW0OdQKMKMIKnxMnshIAOCorwFviLQDvgsVCQ6jD/vWD +fILk8ulLXJMekqvv4T4DtvXV6B20+DqJu/2eVLTvWn8nmoB1EUMKMvfEHmstqwVw +l2cY3RaIcS3qQAueqpENJBIKPtcacYMgeOKxG0BzdGQwb2QXEb25JrIKaGEZTdXK +lRHSUwJz2aMEIsDWNEAZCrXF58DFDJHAhs5vooiBMs7pdc5d7biTumDDi22Vc3KS +tq81qqy/uPT71tSwBOhvyGTvUYmm2ro3GAm/FSMQ3WmibGuRfGRyfOIvyWPIxuFw +nNzMSVvZuWiqSuIy5vuzTLYtt70yyqNI7JNsiNHGWR5B9QQRNtXBBHCVAJGQfXFQ +acaNUahmKuCRNA2RZIQKXrCPHL7wkrsmNRV72Ym9mYCJaGGRpP8AVe9Jv+AJRWtZ +RRs15OSMiGDdqVs28j9dOcbSLzJ/58qvls2iCMdCPJGFPbY3V8ZUYEuW97lEy5il +oF50FlPR80QAEW12p1sWh9TpMxmeQLNcnDN7uy3+5ttlTayLE/UhMxwHHJgBbJd4 +uCLmUdfQm767rslhsMiefa16RFBEfekr+K9qT/SXm0R7/b+yf1fY79Z2lYkME6jD +TcwuMm03NR8KKNou5FuhLXGLTqknqLwpoopgesohoYkxGitMttxKZIN0cIRJ3dxw +ACbHHCNZTkRs3ZllfiNOTKSc4m2EZCX3KO6pJwMgglTWJnmuQ/5KYJ4qzW9m73VI +b8WHFt7XDFrxSf0ItNukldS4pheW7iTf/lTnsqBx5Bip5YpTTwe9OAKrTxIm7iX2 +Kckc2o+s2kBWH7Vq91+WrV1hxY8uOiLEFlhr68vWzMWQoQrzrlvULC26zt+yCkDL +fBAbMh8tRxAthaBd8x3QSUad2FvxoaOSvyp5L8UrzX/P+f8AEWuosIpeme7BlU2w +pBTkyQlxVK3Ql2RtgE933EEF5XpHcO8YSBQA9V8tUCQOxq08yii308uMuFGwO539 +bk+Tbjby3mTxOoy1HVKY8LvVvRCTdIxpiiDwYorlJG2b9KJu55dFEQRHS0ftrIBL +X80lJ8NtvFe3wGpMULhBft7iFwKMZ77AxAlyLBGgwVKeL6iKlxmCHoRy8xw2Gguj +Upohduhk6WKNSJj0wWnbDOKOTlTZoS3eFXJMmKYyh/cZy2xCu/c+YA0zbb4ASFYb +gTUkKnCyvM2i0rey+HTBFTNYxS5wtBiLICwCb/0e39CU0ePmupFoWNfFdjoYqlZN +7IVfcOyyDEBLa7ylFtzjbaWQ0BAtqOOKVKsslUWbIsWl3CMlq5aXuceMAxbFpC4S +2ylFP0JKCMkcbfomQcZg5Muwy4qYqZzBf/uOn6c10e5YWYh6sxxyBWUV8TXTcRHr +mspVXztSUnwT4f8AP+eK9qH+de2lydZ0nsjksTZtqQLmTTYPY7bXZBdjqtXVXDfc +it2q0sRpButXHqjpe0SDbiH1nivuOGxD6q6mFU4ovWGIhp86Xq9p6Oe1sf613gnO +S3PdcNYl7WnqNqa7zEG+XNtnHcel7JsX99p4MU9S8ho3mvIJAriWaF2FuEC8V+aT ++j296T4Iv5VBR4CZNWljSXIoq0LbhyaNAzSg3VtcrlISNMVYsDmG3KLYaXhvNcb7 +HT+K+i8MbRCtAPbOaViu/Tc/ajKkIMp015iQ5UHp7aYhFzSrFBjx0js6jsPKLRR+ +nKNsMkzIe8HhSDiO9WdtiXeGIzzi7rSf7pPgn8JW/wAP4+P5pnwqKmom1iailso0 +aG3xo+znJSTQkoMucN4hvO3RWkhOSDcVVhOKSowrRA19I9QTLjFd/sZ2qLgshBbs +l6ubshQO03jibNtwbmkjy5tkvJUgQdljLTT0G3sPBcmRdB0ORvmRpjKtFpz3Z+Qq +0ntXj4JSUnv5+H5pP91+fDSea16Uf9wyHmmnMFzBZKkC490SIphceRdsGHHB3ZkW +p1yMznSyURpQPUc9A3ZblMvMSMm9OTjcdbjHZLuj8dG3HbpIDZhzveUFbZWM2390 +R90E+m19N4UR2QYkghYNfae0ve0sF33B0EeZ9vglIq159q/Px/mvFJ71frj8ug8b +dnuzmoWpcyTx9uAthz8f3qpG3ifcGjnG44OZ4oyrrZKbYkipyR34jcyFyMnb4k3w +fyqPFJiU00rMR5gVcaBHjcrJvYzdaP66c1vc4BNTl3BVxxy5UXbqfqCQHUEbcx0l +6qlDBqHcPQ4KOt/zSUlD8PxS/wAIvwBPNa/cKcbsJrSVzam6svoMut7rskyKSLsg +vEh+ZKmeyk2p58iNm6J8DL8tyHG5QZlkrawmosFILDkt60zG7k8AFtIleh4I5jFB +lwGhVwijS5gukkeMoHBBDkNukThHQyAZVa6hXbueoNxM9E3pX5Byh6YapbeY+QyS +TZdqRaT2pPhv8E/lF/NXCZ2MZXEnqAyoTrukn1suq4jMhHUdT6Rgjg7DJbc9mhdR +xMCdjusO7gjoPmprchV+2GjayX0GozjsqC6+7aLuxbXCbebfR6TDGlubqQVyaWbL +L+3EYdjaEaVO8c7qQR8LRZSroBMK6GpHstRTHK6cDLCSsqBpebGjYpb9PXQrxa0e +eVK81+aXzXmvzX80PqLar5LGZNWMGtCcSPMnN9TmflOpXLyxZZ7UiOHFipKptuRF +caXGTCwHdBMcdpB25C+vH1Kk2Nb3eKJeZ8ZQF2ZLvoxFZp5xx+4dtI0ba7vMvMeS +61bG0LKdJuzbK/SU+eRu4RcY7rLf3byq8zgYjqrNwFHZr7qdPG5aWoSh6e7DnGdE +6b3NyFO+XSyTYvHikr/n/U9q/mrtdEhtrHawB50cdYyAd07fRHqJZWbvLv8ABLpt +eycipFksuqSelQCQGxPMeVCpdvVWecBbfaMaZkmu7VMMQGlzomIEhNpIN29yUsoX +Ce5ORp1Cc9T3EH2A48grhH7ksecp0zcdg1HPJQxqQ5vINV0axLaitfL4Epizm7cL +Xa8bfI4mbLcQuUJF/o/4lZg0JOGklZ7iyHIZEc+OFX+Uk7Sd5uIXpkj1bO2nwn9J +6mSSlouoyGBUW3QMMlQkRVU0AT3dj8YOlivZNmXjtjAvWDWexUBOIm9SEF5RydNF +8E5yPLszJUGGFbonOMMVukxU3brUEvcDqGz3M8Wl0r3tgtjcw7ewxpm4MMFY2ytE +Jq3SNKTkhTBF1VEvI71//8QAShAAAQMCBAMDCAUJBgQHAAAAAQACEQMhBBIxQSJR +YRMycQUQIEJSgZGhBhQjYrEkMDNDcoLB4fBEU6Ky0fEHNFSDFRYlY5LC0v/aAAgB +AQAJPwJc/NWkeScLle0DuvqRI+ELTNyXeIXJC4TTbkpjYgKp/NO32VvFGTCZCGbr +CEnqo0EWXxVbrKMrVC20p21wU2GjZRdMJcwfJSB6wOyqU20sXU+r4jtRaDpp1hab +R6NQNDbydlUfUpv8oODX1dTFiU6Gs0680wfc5rcXumCPwTe7yKOa6cgDO6N+XNTP +JN4id0/4rboheO8qWqpp0clumyQthvv5hY/JDvDZDWxKflq0XtfSeNWkGxTqZ+sY +dr5paaeiyQKRPyVjVe58cpJXEYsI3TTNQ8MofFNnq1XB/FOh3LmvmmjVPOQts1Ad +2x5JzTe45ozf2dFUETcEKesKTv3lVJEaQmD9oJ5XusnaOvITQvmEDYJk3ioU6fvD +cJ+YMqVWUJ1yB5j0W5mMwNRxZmibc10QAZRb6xRzX1OwWiPdMG6zaxYSobOs7Lca +lHxQyhw4UYI3TYGbZTfmUNW2lEeAK0HJU9NU+J2lNn70ppRv1VxOkocU2vdO4k25 +ByuBUHizty7cwq4d2ONrtyx3OKY+c+gFXyZ8OKYPPMYhGGNyhHLTBEt5jmmSQJiP +6uh8SgIQ+Cf8UAeaFosFb3Ju86rQ9VW0HKUyLWkJ5zc0bG0p2Y7nn4qn4WUxOqqW +Vp3V+RKarZgqRykgE/xTC0NaRUjRviq8mhjW1xT5B41/w+jOXt6Mxue0CPef8ghO +kgerZU4zC+ZaQjJm3VH3J0QbhaFfBba2WsoQ3cclqbSpUdAU7bQ80NrwjbmhGbmo +lDwWWQv3k068kNRA6L9IzNRrN9sHSUScTifJ1OphXXs1hyuHzHnKKfDWVKb3f/IQ +FfigShwtfad4XNDRD5LQdVUYDKpSD71MD2QnGOj+8h1cDyRPhKOvNqMc7ok2TpYR +aUJqZQqp43cKzPJPLRUSMpiGmy0j2l/hN1p6p5qdLnzSG1W8WVNJNPye4sqDnMEH +0aczSlxnuAbqr6sMK78SUPij4ynf47nx5IZ6ru7TWF11c59h4LE8BMZGjKAqoDi7 +xVTLJ0MFpT4pNIDgdR0VYHtHWLXWCcBO20J1ph0IatPeKpta1/W/iqhNfBEiqI7z +f6/BNc+kKhcYfAzdShRFYHLlqU+HrdPADteL/VVhpf7wTqhZNwDLmLE0szrGm+pl +JRkm19VrIhUzUMyJ5brynQoODOzbSquAL/D0HZabBLnLyXVFCpTLHVpHd3sgThWu +yYYFsHIIAkc03SzpQ3MRsq7adG2Z7tuaztIcc9fs4I/mmPc/9ZxcR8SsJWrZNmu3 +8SvJJB9kVQ5ywdQObd2emqZPLh1KYMlRuUs/uX8/BElrsR2jQNBa48N1UzMzkCVU +yyIyymVYDx2sXOXmjJkOa+mLFsapjWPfevUItTjW2/gsO65J4zYN6xuV5LYQT+jc +85vHlCwTKTt3vfwj/VYnChranG1lGD46rF03vbdgOHuP9V5PBtBItPhKx9auGNAw +7aovTb47+9CYR+zez5qhmaa3DZV+1fT4O1nvAaec/pSXvHMBYYYeqT9mC61T+aot +aK3ev81EAX6lawvs6TqU1XAx81UPe7z5gqi1jctzAKxjaTWC5qZQIWBrYtwMNOHp +2Pv0X0OsfXq1hPyX0PYJ3bVusJ2GII46b7H4J+dpPC8atVHQZtLZv9VwsFM39r+S +4y0dnJ5Ks37N+ukD+indodKFGkOJ38yqVHA0z+jbTZnevpg9h9aXt/CF9KcPiiBm +FOrRDre6F9Hwxrv7VhH5m+8G6LXMizoRYyo9tszJBTHQdbfxRnmg3NIyyVw1/KdX +MKm4o6k+/RCPsQfMEOE4Zwn3rnKae3wdcGpHLR3yV8z+FfJUTBFroOH8FTNR5tRp +g3c5Y3ta7hwYUXy9AP4rCtwNOtVy0jUHEQN15cpg4eia04itAfHqt6nkhSxbsGGu +dRq2dlItlPPxVKKjDx0nNhzOkJ5JBTvVVBryRxhzVLZjXYqrw0hxOLlV7PDi1Kdx +0CDqNL9TRpHi177j/BYbGVm1O/8AUqees91+7zVKrAwD6lfLWcxzYMe69oWKb5S8 +nVTAxjaf21MfeG8LGfWMDimZmZKk5hzCJiOHojnjuu5lahNh7w0Ax97VUHNo0cE2 +izxiUP7Kz8POP0VctPgQtKVMyqWUYqk5rq52eRZU8ve7SDun3BsjchOVAveBwgMk +lUWVH1BJFdmZrOniEKlDF0Xh+HxI4g1459Cvobhce406rH08dhzUouLh3/dqFha2 +Lx+Kb+UVHMysB2YCdgsD2bw/Ofqzxn/Zk7LDCnUBJ72revVG6fxi4TetyqLnsDpN +L2j1XY9u2ftKbzpyy6BYihWovGXJWbA8F5SbRbSxAqYWq1xzUjtB5L6L0MJW8onN +jsRUrmqS/c9BN4VV9XtP1xfI/ZjYeCdkonv0KpuPAoMketzRBOwlR7k48VVrRHiq +vaVg6mM/N2i/V0mt+A87ZcKedniELkNynongkclNqrg0TYrmgenmo6xsoPQpxAbw +saywA5ryo6M/AeQ2Ce6o55mCVwzpCec7hxAruht0PVvdO2vxaKbiChLTrHNU7k3D +U0N0AnVVA7NLnZtydVQbHNyG+qNtkL84Q1duER2dMuf70JbTq9q8ka5fQbY2Pgmw +18hnUahFNd2eJodqQRzOqEWuvFG+8lEz1QRNtN1lHPmqZnmVcyqYsb+KjxKNjouM +O1ATOFxlqnNF4F02D1KYAZsn+OVGZNnRCedd1HuV9jHmYLFtNt9TKb3cOIPifQKG +vBUPUfyVIvDjaFLX0Yp1m+C3R0VS3XdNmdStZ2VoQ6SicuXVNAhtkBbUrXcqrqRH +Mo73DbozBsnXHJEZkyDqqZP7Kdm5NKBN5ATeLeUCGwZCce8Vhw/C0QD4uO6o9mK2 +IyUWeyxlvRjtIz0Z9oKezZSPA4d0px/5pgdGwNkQb2lC4+a1mJToE2R9wTZedJCq +W3bKZlI/BNi3EFfKbps/dJ3Tm5ok5VY+1FlYztumBpYmQ4m+TRTDOStbQqnoO8rc +gvAKBpvquULKGZ4cfBNjgn4oI+cqj9ljWSPHdOtmz35qOSINtShottIKBFtwheZH +gmTewlRHJW5iFZs3PPkvmqeUkcVkALBsjdd4epGqkT81od41XDJ1Th7163IoGR1V +99FY6+Z/BnzVD0QsBA84878rgZpVPZKwdWoz1KtFhcD8Fh6lKo6mMzHjKWofzQHv +RMAXMoi61dqrS5Ol2hgfNPdL3BpJuE0FrG2BUNjcjfkgRJuZTX6kF7hbxQm3rc03 +KKbb+CMpsW15poEninktQbLxherYwERdqLuzyEviyp5R+P5kWxFHLI6II8TdQtSE +B98803XVOOUHisvirGeE6rybnxDW2Znyg+9eRvqbHOs4Vu0YfHki5skFplFuRo3O +i8lF+Fpt+0xVSqGN93NYPs6R/S1n+v0CAMaQEy4Epodf4ICVYnQIa9EJ6r2Qwfmu +9hK7X/umxREBau7xU62DUN7jmtVUtmWg5It6krhPRYh/gTMhY11WgRm7F1+z8FjH +cLuAZuEdE+q7snjM177RKaMuaHRsnbaInpBTvcveFPMFan5J+p1KF6ri/wBMefSt +ScxWcXln7wQ6BG+7kL/im3IXqjM8qkZ9UTuqgkiGWWIjIIa32lTbUY9uRkDRov8A +7+5M4pNtAGpmV7iYLTY+KxBkuyO4vmnZTnyukrFDM5ov/XwTAN3scYjoiCPVgapp +vYp4tqrE2C1dDQu6wQPMfSHmMQrNdVbiKf8AFetvKb4+Y7bolpGsIPqVDAbTpi5H +NHs35ZyZpI6Fa5dPZCzBjmw1/KSqb3u7TiI2CwrnZah4AfVWFz+t1lUcrg57cu8c +1QfmYPs5t/ui4PZ3yW6KpJo07370p2nqhbC4R0TZFETP3tkUPMPMFr6NIThXSW82 +boix1OidJpuAfA0VXTvKnmm2qh5fZrSLArH53vGSqdmc4WAxeJqMqw6o2jwL6L4t +7naOqwF9Bm9nPq4oTC+jeKw2Y3q9jmA+C8iY/EuJIzUsIQCffC+hdUOIt9ZrNYI+ +a+hGGJHLGfyX0Vp4eg4QKlJ05VRGYtguDr+BTYP1WPEaj+K2WgGjVMEocdTjf+YH +oXDmkFerULb9Cmj7RoDiN0DcLTkqWZ1yLaJsB9Mb/gqIG8pgsNeapU8rSm5cug6q +iBexLlXa/wDZVJvetmWGzg8jsmOa6k21SmNkCyuyo6+ucH+COaEfcvWJcW/s/mgg +hZc0z9eVzU8MxBshxfeTXVKZaJGm6ENAsS7upp4jqBqhBn+gqxDHd7I9Ylwd2ovm +myxNRw7eBJtCc9wBhnabpkFvqKkTzhGBT73EjULnzBJnVGRdDiyxAUfZUYHST+ef +LSBMbFX5lP7o3W2hITTreCjwg7/gmxT2ajcn1OSaC7LEAFNMHhNSoFQy3sZQZnyk +ZzaQsrXAcTp2TqlmhVZc+M86QmGw7inhbJCcNdVVNOrj29pTqZeG1olODmOuHDfz +j8y6KlazJ2G5QHY1K5+qU9+w0Dj+1r71psSjDc0e9Vm5mO1TM0G6baZ1TXG0XNk8 +mY33TpdJbmb6x5eCHaTBDNIVO7Bpm+agg1BxH1Z2TsoG0IuB7P1dukKYiGk2TyR6 +pzLvkWJVQh6qiqylgmTg6thUuTwO2esW+t5PfU7MPrCH4d/sPCMtcLEeh8fMPQCk +GoxmEpEHQ1XQ4+5oKBFCnVbSwrDoGU+D8QU4EIWO4TYOifD2781cESB0UE5rSVS7 +xghux5qYda3VOHsgTfKnAHic6Dy0Cyg9rAbOnJd9zb+y0+KPDZrJOh69FlqO6GwT +v3eq9bV3IJ1zuuNuZjQGmNG8+aH1mrh8NOKot/t+F3t/es1/3WK7RoAODr5v0jCJ +afggh6B9C7j3Qn9x2Ixb/ClQj8XqQ7F+QKVaqXW43OLj/mKH7PVc7gKzmndN8Qql +iPkmAWToymQXFVYLhdoGphPPZ5ezDty7mqo0gSFWJd2wzk6xNp9yqZuK3JFrB69a +N+QTZOpvr/NAzPAybLY2Tp6hEma51TYx9EnEeTT/ANQWfpaH7zf6sqv5J2Axvkt4 +N/qlR3Gz/tP+AICI7amclaOfolOR8x4advejH1f6IeWSHci6pTaP8qn/ANMfgsLV +tbKaEn/ME4CG2jZWdvyKsZm6cZ5hcv6lWt3ZVOQeJxY2/hCwjnYktysBYc3wWGqf +YuaXmlTOU9Oqon6xVw+as3Kc1MdVhnNb2HamnWHFyuFVNX2WGwHuQDjtBsE8lw25 +Im3dCHQoBrQIYE7NNUkouOKvi/JMf9RR71P99n8V/wAqwDyv5M64SvwYuh4Ncc8c +8vJOu4OpVL6uYYDvezKfQPnCP2hHwVSXVLgxvmYE7iZ9CKr3f9zEv/8Ayqc9t9Ic +JSb1/ImFEipS4SDrZH4qwGiqEGdYQ2uEfcqQ+GqwTS54gujZUHHmIXkxpqZcpqGn +chYemxzW5Q86gKuXH7tgtYs46IEuLvZuqk5tPBO4RsnTyXtG4Tfy6hSGOwVL+8rU +LVG/v03Qjnw/k8f+OeSv/c8nV7YuhEDu3dHPKqpcMBU7HtHD9I3IH0z1mk7XmxOl +zLH/AF9A+Z1gCTdAjtXAgK/5TkHuqE//AEX6/wD4a4OoJ5OxFYruf+eMEHHnOBaF +PY42rWLX/fbUcCE/VX5wpgb8lVBB9VMyxs7dVi3kCbKY9oXCggeybrTfMpcRfTRO +9w3Wg1jQIG/eg6o5eSfv6wR00W8ypd9Rq0scHA8TMkMxDfA03T8U2aPkHy4KOsB/ +kryjZvQhtQgfuLDE/UsHXwVVzjecDVhnvdQqT7lUDWtPZ1DOvIpwI6eb/8QAJhAB +AAICAgICAgMBAQEAAAAAAQARITFBUWFxgZGhscHR8OHxEP/aAAgBAQABPyG6H7mF +UGIUcPUsNZzlLOcXBtOhq6tYJdC+CXR/BNitNmiJNGPvUbQcqquPM8gbDe3mW2DG +3lzFFTbkm31DKLyqtC4F6siwfUzW/JYK44i4GUaejDMBzCAVl7hG9bBL3Q4Y2Ewv +PWK3HIvA2EoO3MKzDfE2OZDVQq5xDgAGE7h6kPdNvMsUV8l/sQZrdhQrQ5H0d+Kz +DH4IjeW/bEhjqv5nf14gaA7aqQEOieuOFMeIyAbRKteR2y7saAZ8llWy89/4RAW4 +FhnwjtppgWUIDAN14g0ONLiYi9+GSUIRYwLjI0yplS/MLxPmOaC2051upRqoa4B7 +izOhrcNkmFPBK/itG315gBdVBghDas5l7ehdZ/3qcGHA/bqIyuLB5iCL8qbQOCtt ++ZhH+y51KI0OwV6MJzFxts27GoS3/wCBXPHBLafLMSK6zhTg7YdsIeYk5wUw5KHj +9xTj5gn9ERrXHPXua4NuCn+YBLCTzwgi9gA7Rd4e+HmPuPbOJXOxAqvMNsm0r8It +56vsRxKgWpulHzG7LF/sxLNoNsIbI2l2sjgRdYwS686eyFcZbuoiwo2f3ggjR3x4 +eqCt3LvPiAVTPESxl2cXQ9n8wUt3DWMeJZLQaAR6NHggyPxKPLL7aIOx4y7lx2ga +6vDwO4jJxbL3ma/juG+T4/cSsCupjki6YHWoFd2AFZ3RC924KrMsuNLHi7/7GThs +Pr1CoIubD/rieCGTKeuK7eptWk3sVzKCqByV9RQpidnqablXDSS2W1zBxDyyHkji +cgVj/VMSg8NvUtqYbxLBFnWleoBrEQjfqarVplxLd1ol0Cw22MifmVtAtnLKE/cB +anca15Obpbz4iX6lUTNVjeYK3HY7lLBS+w/fdQMKvvduA+C2Wc820BeX/IWRMKiD +3/lRFZk/ohytezGbhhsQ9M9ypCfIyQXupqmVhVQGhMCwaocoAtGxi3pyHMmcpypw +a9SwwOSzKdRV9b0+AlhHG98+5hh1AZcWKwt4dJlRAsnFQBbMczH1PLjiV526jEAQ +E2XDO9aPXVkQGgPxevvGdJ+N7WHHh8y6eVtlXTw2h0zK4fuUYB9EppVTOYi9eyHA +/Er7kAVMG/5YAk1WY0wPyTboKbfMun/B8x7tFWnMyltwDcHoQPIswpp5K8SgCK7q +bgts4zhLfO1ztmuvREG5hHL+fmDwrsrVcwJvJ8GufcpyOHVC9u5+ncrm2y84QBsa +cAbfhsYHyV7xnZWZqvMyaRxVO7itta3aoIZuOtOPmVEVvcCl20VBznxyNfHPnpgt +NvqKPRslF7YzE67ym6b5GolNTbFgWX+Lh3xlla4ZK9sLGq5dun8R5mK25M0UvDik +eTJqqzxlgHAdmHJRF0qHoiHh3B8Oh9wsCfIf2hZyGEH3TzM3LJXcxsEK6cbiFkOG +rMTaxAVw7mrJRRRnn1HhjXZr/ZgWC8cQdS8uTUuuoyqrtqyv3KEG6yDQ/mGlqXPf +pFNgaxL7JV3KuJQY4ppvxASPypt5gJVngYHqccvuabv5lTbd8TcOrwVb7kEsjVF9 +F/JAHbfGcy3XNOdph9qwtK7mebNYVHkYHiC+hxbnlN/caHL0l6FSmuiO1O1t8zkl +hdA1lm29n/iMUWdbpXa9cVNI/wBICXj6/MQXPBp4RzeHHavVxHGItQVidSR5B4D7 +jhs8oabt8/mG8A1wC+zaY4jxyECC+V15iLs0letIiVMhVdtd/HMxm8nI8jmUFxyh +8n8yuGhhaeOpUCuVDiXnB16V4PiCwanSX8rg5lVLOOpliTuCXUtGNsK+8cSkG9j6 +TwbRQuudzzr4lI2yLk7mQ0VSjW0AbrI3i+V74lalivetOPcvA2rAW4sCEmvqiSUZ +9BrL1ohJhpusPFyzetxaHBHb8a/TbFASjy+X2l8Fe4F4A7WJ0IcaBTD+JkXpYQRW +POeoqv2OFYHpNbmx1c3buxSz5TI8sto0KWlNGuVivSStJXZTBuruJ1yoMPVG227x +KOABF/BujZHI/wBUR1d2vllu16mpMg2gakyUeML7ZPuEv/YRSptqnrfusRC9oDme +b/mGZGnJoK+Wv1KT/wAlLwTCEB3wz7iRDZo/f6QRQvVd7eniY7qCHa2s3RbNa3OD +U9C6q0PZqqBF499w9rqhH1ZcRIrVT2n8rhx2oTttyXz4DC1CaPLNCFS1Ill9jbO9 +kqaZzDDS34h622HAuuPJ8TVGV8Wdfl+Z5v3r4ea4h5joPPlVzZA68WZPi8qbcYio +YoIM6twE1c7FZht4GR5WknxzFvUBmmdYP53FG/BFx3XD/wAqvzGI4mONH4+I6Fst +5YSFzQo6mPSYcUQXWnylYc1DzmN/xMe4YldI6E0h6UqhHInMBuS92+jzlHvwDPDR +F8yn2i5WGrWm9xDl2L+h/wBn+tlqXzxLF9aDl0faD2vjtLa9HHniKAw7XGg3djnN +jyiSHB+kVMnMNja2shZSot48zPDCz1eX8wb8lYUMYOfUxSG45A3c2QzsHgqPmRuW +/uG/zDXGrylcNY+OuV4oKlclhVa7f9mWXi5O6jaKdCRPl6hb4sVIWbp5olFVKgKY +CC0dioIFA6KeCZDpraQ2Te6IK+DHkHaYFf8AdfibYHOO9YM1cLZrnELKrv8A23Gd +hUDxmiBbjdKC3i4+NZaBqnnMcxUtvLF8qxrn+pnUc4cvU3JV2OiJfjkg1tfk4hYv +Pp+EGwwjKtJmwQHFKycQJYmng7l/I+o93YpH8rc0Ajh6MMYVdYic6OHuOhUwvP8A +UustE3OeptM+qC15EpjRspm440xW4iAaYhyzTcRYlkN9jJC93mK5reCrU1anouZR ++OX8mVq88XGN4qurO/F5rzEli72PPHzBGqYTT1FEVcIxcXINudlW/FX8TGcTmcQ/ +cq6v1IS0NKfiLgTqs7ZdXWQ4yluW8M3AwrzAav8AMxRxwNTNlRo2x1pV1nO4ehTw +jH9rS9+5aw/RP7AvcWJijHeDJ45nU0wh7qUlqkqvEXIB0cc/EOq1L9QURujU6mNO +s2dH5lxyt4HzBnea89B5uVXKlV2cviHsUqXRset5md14JdpiCvUphUTaTfmVMsSX +DUqdG+YjHVWyGdOmnHAX7i6+mAWfmpzeZYndZvE0yFD2wzMwP9X0xX7XFQfxLTGi +n1klT3CcRatMUrXRAKNvAXiEzH5lGXtPmipWCRerxAMZeD/hH6l8cXuZCcCsX6mg +WHl6QWpwP2QAMBbO3q+OoAwovROiGBbYOeSGA1D9BmAZp5aeqmHRTO9THAavR8ep +pljOEtGHth+LmNO1wCttTRq2ay9B99QiU9+dqD4i4HIhz/wmStnmI4ZzYl7lYMrg +s9BNzkP2mfGlF3eoH1tb4aWfnUslX32EUa6qisEsCKZQVYdS8V8rOepVSyhwvHUS +11OddSuuw2Oh/uI+ZKOSJk1Dc0yk6Kc53Moml+CZrNqu3qoSLjDKAbPFswsm3K+G +J8ORV9SykOCsHasa6JKLeL3TDqBKsfULTW+l1G7bzAPEz7E0cTYxjdtzDPuM9uvU +J9GAN2Li/Qp/AfbcW25es35jtxXRA9jmaPtn2j71L01pkAxoYqnscPmVi1H8kfrA +eU2aOwhSMAuOX5/cqyJQvBME7NMCy14DT44qY3Lkq23bzLRvVNoVuNQpUu/ExMwt +SHgeJsq6GvfMr6oCmUviZq3QYzzE8U2DqoihEO5rNzLwuBRBA9qx9wx65R3BzWeT ++Iphuv7L7lTdtnh04mHJVA3CAAtblIM5tgc5TLk/KdGm5RQrU7BLwU6YR7ID4iMb +oB7MSiYEDDUdmPAJW6B0azCNCDLITygjB5uDxYRXghlBYxK/xA7KKyabmGxrBW/E +yhN0cO6BAlCjSbfEbknduYluM1otslYXQfAlQFzWoZKUW2HMBZLfV9kRMqyca/3M +BJRVVkmppFcMwPzG8qf5g4myl6iYexFtxDFlKjFXyfM0HEHQSmR9s6c+pe1TG6hl +XETdHMUa0XP9c1Wj1YuEawK3hcmyBDTTdXHo8AbxB94Bxh3guxzOcSNW5VQCQAc+ +/wBTCkFwY7UIVUYyNYjJInkAf3Dr6OYNopTERd648ShtWQCj/wAQBTU8nlDGKWus +v4hBrBqr/MMxWvg1huobYK5GkNZGhA3pC1tSwSlQGVg2OODFeJa6LbYAho+G7c/K +YeIUx5h4Zg2fHUU5aOiZ3Tf6lG/8SwL63MEkEuZYOxvl36hPTiFBMThGfgvHM4yp +wBeEx7mmhqfhwIOpk6jyj0HnWFcnzCwGGeexcRtOJ3wMRfxXmXTwO2DrwxnQZaAD +yy66j4E3Ptif8ixB67YQSIEUyvApteB8QFbNh1SVSCXY4qayZXUEWwJn4dxO2OkI +Aw/5cv8AEtrNQ+v4nXOO5Sy8eIXa+ZrHJ1PK1ua0zGulvO4fHgH+mmWTZHL3uJRA +Jg2GpfcqJwJZYuocJcic6o0wXwRQF/cTVDyxMOCN9A4lJW61Os98RFM2O7JbuXJA +D0/bXjUAes1sWx/caOM5itEjxfiDQdH5lK1q9n1KrY9yv4zNUtIjXuAQ1eDiJqDi +3HBrVq53CKk3mYY119aPwTmryx7XqU+tJxBTnZyRUbdeSUwHn4mcm3uGNdbIL2eY +XFvPaYgDmuOWyz8QwFSjwTE5FWNB5JVBZFrowqJYq22Aq45hj/cRa/pbAPf1PIZu +V3AbCPTXeYk7GIttB83lzXSYbIBXTH9fEvoIalX/ABhcbrKN1i3Z1zDY0rp1n1cL +sc2aPGfPB8RvQXYdHPScoQ4l4Y6nNBjWdSrERnTo7hbgmHm3ECHQ/EBUA9XmG/aF +4hZ/DGwYxzOKIZMX5zqNeQMGmpbHyDzG7CT7wfGf3AgXhQMCFnd6PzDVl8CYPMpR +Ft6y/p+HFnN4oiBKzlMfCrfWY+oMVVnZziZkCQI2nMulay4Wg+CDnObzdp7xKaDD +kVz8K3GkC6g4U3fUZ4qU9MMHVp1FZz068RzQuUPa+SA6iMODdp578Qhac7Ll1M7q +eGaNZQOGXawfkwP2zcK97lt9p3SFlV+U3v8AE1w7qPLe2mpvm+5pQv1M0wiSj4O4 +ZG43Jz/cBSGnYOooAcbLJz1BQovQOfEbzDE4fbC03ZP+GWryBoAyfFTNfRTAqhjc +6MDs9upelB4JPVbmJNEfgrufNRuUjuNKauyYxg/hwo+prkMMuXX+u2KcedymF7CB +j2fxGsLgrFlPhLEvuDlis8QoYbLgl4LAfMwEt8ro+CPC/iGcO9zwJxlqWBcXIiYP +c7W+JRfKWxzM9+5kqrHBBZp0dJC4KAHwkAIVPzXX1EU3bzEwZnel1EkC0RYNpeD5 +j1z9xvdufczTF4d9FRgoZ649JYu5G33LcCwpEw/Uuj3A6WOBiU/xJciHPn8EGYiq +ywVeKTU6pzw/cfIIpxpz0ddQoo8j2zO73v5zNeDhhpdRbnuKtHc7VDyfEXK+Yy7D +PcKbN7ZalmXzG69sxsxbxcbMRk+hF4gxKMpz8DmVRusPMTeaMSjsSY4yaVlxHhF6 +Eyz8xCZdzn89RA0Wsb5QK7gtPcZWhxDx+o+rhZjO/wCKuOQe1hBVfLPYQOTfxCfD +07xcbDIbKnwEVMqqq6rx8zWmVQBm/GCbIVXtXxF83IGRLY9tGm2/5TFxw9zwfmdv +xBF2ubiL4+Z5VmLI1Jdbqpdbqq4hbYfcF8puzjZfmUMs3wDMEG0+CE5XwrliLsaR +Klyg3ybuC3LV/klgYwV+eInRRhbXN8TFeIUN7x/szLdtuecfqPt27F1/moYggBYn +vuC5ev2EFloK0J7YBdBsF9BU6PEpwYCUpwvOC9XK0LkNS9gtLfb7NQG8BWyMq1MQ +a3WuptXKWMwVAmkxxVZg0UfBMdNwLfFBLcPklaJa3Sv4wZhmptqWHNh9RHLLQqZi +aIr/AHJ4jBb/AMRtRgqvz+oFaeFl4uPqMB9uV67HGhuMMom8LW3EVDEkWhSipeG0 +10H++9z5FVFu3tmkN1tS9fMoOuESl5G3fES0TwrlAOj+xX6gyYIUOvN9wc4dJKh8 +Fi9+NxyYvx149On9oM7jQqa/p/8AFHNbZTznpKvjEfBk1MPKYu2XnweYqa8IpOTx +Ux8oQZybGXuB3KtdPHvn1KCaaEvU3DMsYqMbWUKrye44Lgy10YKrCdSg/wCwEO8g +ZHS+JzMDTNLKnDuW6NAqZKF6WE/L1XA+9MK9wD6UvJfKYiYOtSw8dmasgKWWF+y4 +iVvyHS8QLamOttFdTk9W7ByVH7PFR0TMYb4KDJwCtMxSnh206+k1fGNahVtsZ4+f +yGY5lzmZKRXMX9CdDXlj/wC5iKrLwMFDHO7gNcomBedsa8/okbnbRdot8HAWCfs3 +Odqkdo2F5adTQh+Q8zP5F4zcvyuvJMkulWS17ij4wxd8L4lXd/biDMMeW2DfJtjP +wyN0HLo8z2tHDLa/mJQlRab+ahA1rnDlmk8ViVoXgbLT5feoSKdtkvy8qPaubBE1 +iuB49QmitLeSCKTIeWWB05ADWTpf3FmNq8MmB5cajLdUDrXn53OyodGFablMqzOR +9WBpo9T4qlqL+NzEBa0pmTF9Rcr/AM5fQFvpiJ+6UbhZIsCE8vthCs0Ih4ADeVjg +Tig1uEg74UdPuHWcImxonav/AGJ4EhXKLRxTvWZpG/X5BmDlnOGTuGo58eSZ0ikK +aftM9nEpCCnyV/jG+E1onXiAj+u30agnaBp2r3CSrJcOogwaMfM0zhTJbnEX+HiM +nOcuOrzFKCV8xRWTX2dEeVbEtsn5vnhU+xBTcsbSXdtmJd7bgq35qFOGM3ANrSXo +Visv+xMQqKuA382jDKveWN+LmSPW4OGfMu4WmekEH0nHiJXStxssRfY+SNXPfaCM +heRg9wFot6XKIGvNriGoBA0dHmVFUb0luow0BjL5maD5wfZYfqPs4N3wHlmBZbi7 +/wCpz3ao4vzGmFmLcYewCYsAhjV74FPKyuG51T45CSs8uphtkqsQa8SI5Op9lTU4 +hT44nOpvv1Psizd44YCAeumYgVuLV6K9V9xFDRcFUn4hHbuwptePmZWURcBj7SKi +nhp+CVEBs+LFIGBKzLgwukCEKyu5aU+w5gQz7UJlBTrhe2ClptUKZ6DwbSJJd0wj +HRLxo92JKjh/E+4S8RVkU+Y4blKXCl/4+44qeDmYXUnZ6FjJgvWs+WxTtXUMvuMA +or6CjGtKIbM4s6d5ia9JZuo/Wn4hHWSoW39T/8QAJRABAQACAgICAgIDAQAAAAAA +AREAITFBUWFxgZGhscHR4fDx/9oACAEBAAE/EFpQThdFmv8AOGtVs8HO8Ojo5c19 +YFAryc5VexgFnePeYOXPVsDX84hRYgpNkPk27dY8slUpSArru4mzGrWkdG/rWs7c +AHY2eQWzeEmhRGp3PJ9frCugguJ8z9XRiZhJPyH4794CMg+08lZveMHIGsR0/nea +DbzLr60+ufecXCXQIc34JkE1GME3aO4YIh0BJdDlnAZKDVVQe74k5ecpBMSkF+dn +TianUgwG/wCcSaidU2l35nWGoAYS3HR6eOnHdgh0QcKPt/eatjBS6t0cFeDFgNYJ +DQvN9ZdSVJqadP1h/MRVNfJTYfGsVqLLb7iu7yYm8Kq0KR+HrNCGBxOPIu94LI9b +35awa6xE2d4sZC15SvwFmEwpoJxiQWT1NDjC+Co44Qlho8XDNpNVDe1pOK6MgCCN +w2QjkJPbisKEiDdjnfzcXGAq3918ad66mCBmgi6x2Fo/OIoXkI2uw1sLDvEMgqqN +Lrzx64wKUWUaBXdCcRzhndCBBeZoH1hKAA2athvflwk0jw0po3C7mRqYWoel8e8F +9aA13UA1tk5xwgECItVjTxL5xGDVkBqIhw8OBp9D88h+OM0UgrYGIfk6mLFDFseX +k48dtY9oWnV/ltr43kIyvaknnrwY+W29E1r1+8IIMbj1/brCYsBsDaHykjzrvIy2 +cRyaVA6eKZpiSwnC6kedM3iSBl3daxE3o0311loVaDyd5NYVTQQ8HvJiriEVCron +vK3rzdiZKPbvBw3Sgp7gCVLVvjJJShDZVBNdi8qYyJCYKIKUcy5CxF4HPAf+PPOa +FFawh5GpDdMRofSkaKPZve8DYbJsWdqvDe+wyonWDeOS73vnnA4Fgep5pz67zXAm +9WN+XXOB4Y16oVuk/nHeAdOdoF5nJ95z7FqQ3z2uPeFSAViQuovNfwYY0PDKokuv ++cILLbAotlXjam5m4IQGbDpRu545wgvYjY7l1XzcI1KgW3RYjryY5xTxDsVgcYKF +6jRV9JMcKRVqqJ4+P1kNqMWI+nmH7wePbP8AJo2G9DhyQnQjZi8jWk+8QtTdTpeg +0dD3hpLvUExtKng68uaobbHi9e8lIIvsJ49Yh6Hc9R+QPGJ4lAT3bacBWeph0+QA +KkGcAva0PGSjEGrD11f4cI+WkkJA+69uNRuxpBdJxW/WAi6KbXRKBULNc49pBp1A +4cr57OFbBAbLzXPDA8BI6aqXowzSgUwp3Pd85BADZtNAeDs984e6FTQ5LqK/eaDG +3SFZHH/mC1U1IRpw3r7xk0CKgSo63zXELqQSo8aTfHGCxATXeDyPrNHCGDfRg0ig +UIhd+xx7mHG1lRXl405rggY7je2iGA+G4z2vBv7wZGsGm7orpA/W8MJyGt5UddJN +eslRObw07bBPBN9OLg01r0nYag0jS4BRBUqPgQAeZjXJHbnr+3DWTqmLRR09r/jI +fB1yH3gbNymPQcXv6uO8d3akHPYiei5YIwwADp27Dkm7XEb61h91qLSHAAxEVqns +OA8vAespClavNXeBGTA7v7C2u+PGPr5Rs9j5VO9YEgAsUHKzgPOGdpQB3e/p5wvO +jEUW3brj495Uy5AXW0hzN4Ta4pKB5DzNfnDssBtUxB6fvHngewEAgf0OFoEGcX6h +59awpwzE0ekrtWRJgXzZFmlUKzn4yUfkJciF+u5gM22oD3TjV/vNWG1ynXJ5X5y9 +IlFRy2D+sPQ9qBPrQusXSm5uo2+3qYcNajnYu7XHFmUXizVQFdw0TiO6Zxk6FAvB +EHjiOHFa68c1XhUhoau0w7FUXbx6w5OpxgGAO9lP8ZBNmFWeMbWEFmlqnBi965ye +9sFJJ1GXxgTmwgBX30e55xRfYGtB5fe8sQDSDWt6Pj+sEK43wbYnEg7zgPAmJvPi +8G8gAi17Ff6MAcIdTQbb7+vMyVZUjnQW8yb+cpNEQWDd3/BiNIzSpGGzS2eJjzaA +W0SAOteU1hUDClmowPY9ayXCqa61PCnlwI0DEI8j838TFAgpkD1N5mQkYpKgqH0g +b3MCOJYPoj7PjFgj0jfJA/8Ad4Ab2iWDb+cZAmt3fIm+8fTUGwDrbGYUHIiATfHl +E5uC7EG4Hx8hznAm6e3sdHd9uLvoztsTYNiNn5wfuFh2dioPBDdwkAeB8jiCbAW2 +ZGHzQN5MKE4PDm+p/GG9vkEwGppXOEyxEjQ/4DASHNOjviWLe8IUGzVi1ff1j8yJ +bkGQeb+cQnHUIwCWAef1hDVRzypvfX+MBLU6cHJPzjjvrV4OWsr1MlckTnrpaqfO +WwJY0QxC8jyM1wKSvwIs/RLlI0gCWxarw9fGHTRDsDqEtvn0YwUBe89u+P3jgM+c +BF8GucI3VOGakdUrXm3EIQJWBFIywmy4Px5NwgIG1dPe83quMgoHWtVVOHAouAAv +Aaa+XvA7laplGxSryJhoAlSvbboTc5xki+cNDY5GvD9YZkbDVGIHVaOFADCEqC9f +x5wWEsPMA0U8m+s5aZfuLJF6NgqaiGlGnk9YVDAHQM9IyINvgmACugDSe06zTfMn +8sYVD195dk7qagHsoX3jd4SRboC8LvrvE1oC/ZSToPHOsDhCEJbnaXtyqkkiboIK +kpydd4vduNBoLHiwoDeMMSjBABA8cRl5ygN3Z4ek6Fx4x4XqbfaERDcnm84GKw2A +6IGzv631ikoI3xh0i3sJ2iYkJygiqZN/CUY0n6TEAfK8bptxQFAskcs07HXnEy8o +qd1lsj61MBAGCoACmbITq+84yNcXOt0iHAec5Vw3B1ugNAD5MElMRYaAVE17ONTF +fIsOY6itE1KJMekQeymiAaTQp9Mth+ZI/jNjp9JlDvgyAa0OXgUXeT9ZDlPN5fPZ +suaUUUNmccnecWKwUIdjpriOJhFnSJFPZtr4m9lCzjfONCWNRXjFCCxRCNnE/vAi +rR4G35XAqQiavclKL1xmgRFIliUdj/OqSb0VCY69p35wcKA0ilt7wCt46SU6IACf +jE6qQEiIqgERot3Mtvz17EhI6V8C5KirIGsdwPPqYBWNI8FZxsjC5rzFJFwWovg6 +fDnsPLfNxCA7k61cvtLkEsKzQOXRqmJjDzwqZpEp5U4JiCWsgzHeQEd35w9A1SnV +SN3C8bmBCRaX7pXzO0HxhdRYF8Eq8hHRc03ZDMNPpm0jW3dvqFfIDnbmmEALmA1Z +qkkeBJIsMMdGlK6BSOQZxO8s9uAjSVP0Dvkcoib7VteoEpyceSsoqQiDNBS9NxQx +NFEQydEqQUOmMbjFeOUPPHGV3EGFUQXZ4Hzmjv8AtQFL4ArDqZQQvjdQrwBe1ODK +MQ59M0UUAPT8mBZ03n9RUX4zlTTY7A6E2v6uFy7DCW69EINlyA2KtqV9joDFoStG +7X9a14xQpJCVCgZBoG1TiZtJ4MPgkHyZvU0ZERB6rYNhfPeLArLgbYmsTU6pR5do +XscqkhkhqCb3oesY5MFZopBSV4/eO4YMra8Rvyt67MqQOBkVEFFD82c4TsOUWIdi +52T2cv8AIkieCjoDA+dO8rsCmF8TwlyNv1jK+XLrLVlhvSJ2YfdE0K6BoAaCA4Fy +e1A9KIbfQN7brYNG5yhN8mhOlMZav9phQwo0qDnWKxXTVCaQhEAo2TKkPg08khRN +Dkw7AA3cGi/TJsIChTRDHdifpzSOgnEPIH/XGpRjgQb4VTXvzlnSRju0aK+LcGJA +ycfw05AZtVG9PvCwo7hzcRAGHYZMRZVugUHhNOJWkwBFKukPlka4JskVYQhfzhFb +dFVdtG8sxyU7kCxJ6+OcmoGXiLuOEDjt6znuNNOgJ1dq4VZM1Y246hOgDG6s3sMK +0AqtO5hB0iARw6yMbTE0ndK9hleAh54QiRGg9pksVYG88eTvzxpMOHIKFOvb04ZO +hrb0HzwmHnOUbDZIHSnnELwgrO1XMgFuE0qXp6gAkuCdU6gdEUmk6Aex8JLgCQI2 +1gNhmHySFnIhFwUmz0M3VJwNSdkPUCMwQmLOabCoJbEEpZYDtyczh3xZzcdfStop +RhE31+cVG+QMegBo1TUxjpDSA8w5yoilojZ946+HIilJjmPFD8M3+oMleHIU+CGA +KgSvTx8Y0fuOigPiDCIgi7p+/nIY0WLKLtaeDWDFbLshVOBfyY2BBSJRnz194qZM +hjTq7iTrAgBLuOyz+5jluDrPImwdWGu0xyfjBggIgONE97cGqfeeWFRCTd6Mbzs/ +uGOT2UyA6b6xx5AokVu1UAEFHxWTMiRSkPKHHGTNrVVHnJKD5NnOjuGAbCp51f8A +GGlmHN3L5mn5xlaURT2qWbmujPLpJ0LFp8p3lzaQCanIC2FO72qu1/h0VYVG8Bnw +CyRv5KAgircOqNvBc1P9iUJAb4zX/cIkdgaKpca34rGCURz0BKbvBNBPFoAdkenJ +1nVoh34OJiRFTTLy7wY0yW0D8l9GHhbdtUD70yMgchw/0GUghA495oBzfU44zuOB +9XE8y5GyqORS35uIRI3rey/8YcXzUgT+f65o+XSEQR/9yiYiK4PShzfGagbylBJ8 +4wmkMIeUdvO66wCYm4CnDqcfMyCyPahDVDtYTiucfdIzsdlCp5s3cXuzil5AHjk4 +1rBCBK58ldu98d8mDz0SrR0Dip/eI1GQnTXzvoxLe8pU5X83wObU2xCVyrwX+cBp +LyALIuQnHhyQiJMAEE7N55G5Amgw4oTYJ+8VxU0CrPLQMmsdN0lkLTyXSnxm+S1N +Cah09fWHFLt7rJ5J+HAAcLYPxzw5eVmQmn48d+8RsOcEvDPJ+N4JIYECA6nvDBpu +n9g/hniXZeGur3g0W+Q4cugA6Cpd/wA43qYVRCH4XNfHcUksEnafWMBGwUTp+c0z +nwC5vzUHsHC4JH3F+fFOZiME1zW7yfhxc5td06edzzm/IIqqOF6PEy7HDSyBDfdw +F8kDS2SH/mW4oht1fHtrGLhBoe7ZDcQ3kUj0UUSuvjo153gJvTjVBaNoHfG8nBDo +ELtDnWvxh13sztjoOQ8XNYLJJRNs0ef9YAc5ldNnUpd4S1NICKpjia1uacOWe02D +szo/jNsEPXXQDwznfLggrawBOGd1fxlyxWsxwS+e85SBsoTl7LlhjYEvfMNgPLiN +c2AAkHxvJ0AC0p4PFtplzEirSo4ZTPG8WASOM35I/wB5EVbwN0zYV28TY4JwAbL3 +kiQvhj8/HrAFPLYUfFX4YKuZ3y6HXHPjGqtVBPU7NVHluNHmEu6X6v8AzhAHNWi8 +72Q3JnIwKsYae3jE+HscCjW7AOjFgAmAYm88dYQVmvpty0frtx47FrPIKbj/ANyN +iVu499FTlrpymnWgiHXI/nOUDUu329G7+N5CHhQhZzJ5cVSAsVHDWi9p43gRncld +pOmwTFLlokJfZrfvWJMPH+qwa267wkRjZecDzenT6xHoQApwAOGYHLqOmnwa+zIS +IdEKpXvW+8PgWHMBu/fPrGOhgCBYsvT/ACYZpWhDcJ1OfZlqCUhbAicLrxkNIn1i +/ng3vfvIRABur5VGvn4y5zFNPTiQHpppHXeTNui6XvAVhQ00m/8AWIsnEcWC9AFe +nJdsMu2BejZ9Z1bSNIPsO3rIgi+NAXl5n1rCJ1w0L2PwaMM09CGmHD83fnAr4Qx5 +ajYhdPWAfA4yjl9Yeg12WAx7Aa4u0pAHUNkbLd8mRUWBNSSkTr2UyoEaNtAvWUOr +vvE4AcGrtfS8fOAgpBMVoArUW4SChZ6ceRNaOOMEvfmHUx0kr884bDoFsFUu9/04 +LCx0RoWdLH7xg8ALvIP5nccPg1B2t0ByPzOcEEug0Ao1Yf7yVTD6Hkf5xTy3blOT +w8+HD+5RNE4QO14OsfyuGhgp4pz1znSrBa3hvWsV68hr7XjacYFJBGbFuvbgopTg +NrioITZPT1iYBpwNrgoLuKVEwoZDSerz/rC33owJ6fKx+Llxol3ULLaDvEaQ5Cpm +07b4zfFQAb2mjiaPOUlgUiFmg/jNqDwatrxtt1j9OXpLVQ71TBsCEI3W5p9csxLX +ZA6WzS1/zi1uo1x3rjmTz85yQKwB069P1+cC2jsAAXOvOVFksgbY7vl6wxZMCXKK +gEp/Ey+u0ipY2HTeTxirUKYo0FJx5wb2CLjrXQP06zU9sQ+Qel8bxTcBXqFSPQM2 +MvDh8ShVUPKbK+W7ig4hddrH7+sqYQ6EvA8knxg5DYLuDIXenOABZK9tuL7v4y/x +oiQusZ4pb7QH21iRJ2HCgGLRWapy5LII/JwS6LXJz3hKgY07h/eQKHeda5x7EBBh +5naNJihjVbGwoj5EPvHL8BLyuTneWZPboCC3tLlISNNb0N8c3I9GkBDu+NzKBC61 +CxCeO4+sSxKKB3CHAd/eJ/DQjSLNG3gwUhOOABoNc1+cjDzaSs3mNualN7aAW66O +H2oLdBIONzY/OAHCYAgEHEFP940GGusCykNyuXeA6RHaIa4oPXkxvEYdGWXvgnjJ +yUGGz3tAOcLKegSV1/Q5Zzl+oRyVJWHmT8YNofEoPn8X4xgCSiFDDjzvRk7pRGNI +UffBikvAW7I9jZrxkRNWKwF6qhcDmDkIEKtuKlKqXfP+sU0IG96c4NiOr/PziINe +C3X0uFYqb8j59ZtAqdN0PHzkZMKbmj/1kNguiEfp/nHVlglebe2O31iBaF5qSXpf +WFT60N4B9u45SkSMG+AnHh7x8jRjA077nHzheYMc6bH2cT3iJJOlEXK+O594q19n +EnE3yevbhvVdo1p5D/TDjikAdZ4SbnjAWTdIoKF06a4O2s2XnJV0rhDhwkIQom1S +F/ziRI7PrwEzyB4XFgNOagRQyPtlDXNyCmIDXW9E8Y32n1ZANmPmkxFVQ+Aa/f8A +xiEB7FDfxPjJzLklfE+/OD73UVhu3bbrGUiiwK8wf6yf55bR3+gyGsDwtbjBoJsp +tjHZRTXuecGgp4HeMBZGALr5xGDtP284CMFGllMR74ks59ecZBEcJDGhXChvZeAF ++MVQJORUCa6O8kQ6Az6E5PnDTiHY0746vjEmHgKJJtTy85SBAQOyNm+hx2cNzeSD +t89ZpLtdQbwTX1l6C2h2bE7xjWkA8QvLaSbM/gA/JDAfQ+zCzw6EVQbq3hKOoawl +a9aQLx1+ztmGlS1yBSWAOziOTnQG8gTlXR8ZYjoK2HzHOu3xhmEHik2bY/wy7giA +UXl4OB+sg22gUvl1ydfvAUXgyvMNrt04ImxpArtfgMa3FbMU2e8XRottbX8H5wl7 +qXS/R7yCKpoBp+cRbtOA4YkUQNnXowpVHIO8kp3srT01gDbpF4SYEkFVKJJm0KMF +vm85qdOC7NhObMBJVYRA/wBL8ZZhBHVTS/394HnE4EqHzrvWVz3JChm+KzFLRzCl +RA8SXFd2UkCnyqsOzxjIo52DnlELR+Oc2CayQkKDhrxxAeXEYADgkrOdDT94Zkze +yAWci7guhja+IwiHDdR4r5xc5COpB50muzXOMiEQgGuehVijmkkguZCnLAc3eDkM +KMldFaFcD7YpoWAYA7WjY635G5UZAEjhB1OHxzjNaEIS66/H85LpQcQBNP8AXGBt +ioKPZ35yBYQ0qVzDt+s0+F5ALT8YVAY/DlsmnLXGMAEnO+v84eQZQhccpIqngLlh +4Fr8+L/XvNRKq1sI+fGWYeMNvX0OVhSFZdz+MbagKPDArJaa5dOW31hEY2gWUK5s +kQkGO0+9fGbjwAAEnB7feV0AhgeW+S8ZpHjZDYFQOW+7zMLOku5MN3Hr2c4MYWcM +XRidoaFHotm6IRtLiqLxzMXSyELlHwwQ8bhinAtJiRx9Xc+80gZzgyLusRxJ1kzd +LW2VGmSk2uLFU1djXXICN59YvjLriFF0bK38HE8J2CQ3G0I06fJjWnejEBOYD5LK +2TlJWryIfzih9txEjw+txy4jSDR2Xg6jziI1VdKofgwRXJAnJXAEq8JfWIY8XTdw +84rkSd8nDHSCCB4cD521usDxGxK/75wDkBCq5+sopWjBn/fGFlQcHfi+MunOu3KS +G8QIDIsohypoG5MiLYA81PE1rEFBUiGBeiJhlNPlbFPTjDoWoiLV8JrBiwGtcRum +FZs7fGGdF+h8k3dmkHgdYlIrRDcUsQ2cgcmbAKFATw1vXVwmThq2hHPlNe3Dvdg6 +uxLo7DJ8x6MlUClOF26RzeGwOgVtp4K3rW0ZUeATo6KdbqXe8Maw27QMu2AaLM1S +sdSjtdKK6owCi2dLUeNCDsMN7vuBaQV75wswUDksJ3/OHGSZmoCHr1gLZXZA3/SZ +USJyxUPXjDGN6U+OHE1ZWo5ohNtTesNWpqQ3ifNx+x5wt7BUqi+sFqqUBsnnFIUC +66/F/wC1msg00Bzf86y4h6Tg1xgVJOooHn5wIqbwQI+NEMJZi+Q7s9ku9YNUJKwh +LO7vnFWKskHok/LrziOVDgCCaoA6b8uecvUVSULzauWveBiaFlqFfSV8OL/XGdTv +5dOUgJJ5unvhm3yYLpSOmxLfB/OUCgDKedeIz8YpCPo3SMHvbhzM6hk8mvbMOnCY +Xdg9nOJe3BQqesJRuAZ6d0MkakQ+BrAPbBORNr0969axnW5ebnT64yaCcv4Dllc5 +aNMOM4NCopxcTCVW3tfZ8YgkJUI6w1pkX5ZzE4xyHvC6HoT19PnFdNKscnGsaAU5 +6SYGAmq6Kd5DfTrX6/7jDYg0fAx7yCIA18ZysXQUIX94ZbKa6D3Xc0kx2gJFYg7A +EI84jinblHXZxUO/nD48AE+3y1dd5QUPo6GjUcO5eMe2jURYvRtH7wEgKgjBdNcb +XrFEp0zAtHLognPeAQRoD/laLt3xilBCFQFKRj6cBMWsKIsmyml6yj5E2yKGvQ3j +CcTNxpyHQKqrmjN1kVNo1vlqfOXJk/RqAAuiGUIWAiX8vfjGAbhI5Pcs/NzgnyU7 +mPVP1wDNPR0cQMk3peW+cEEnjZie8IHaC8P9ZC0Ltpp5y1r2ai8fOHStXRs3zkhH +QFHf3g2HYba/3lNkHqv05uUmgRfwPjAkWC88OPF1XSY+blaq/wCtpPGrc2H554In +Hvn1MpJRNSDp1sTvyOU6GmiuSfn4maBKtcQs+F2JiHJcVRODjTo83F14+qjV5cH4 +xg25b5TojjZzthOw5MAwksSNnoE1Cqnb84lOZEjgJ2p/6ZS2ApUE7aFfk6wtXVaq +TaKOu+sQhDDYXyTtd4KbxiQaODe3AQ2sgIUISNoHnLRlLILE63qeDFBYHOS3k9uz +NaiegBEwaUTUrIKHVUkJ4Sc63gaK86fmZaD9XLzvEkQwVervGc1Dc1q/zjkjZXeM +0itujQGS64lF4wyKR4Df1dmNjT8BaExaIBG0vvFAQx2k6mX1+80Pc6c/GIHt84bJ +dDutDkcJDLpPqL3OLzMZFEAVVMC8xpkYT7xLgvFK51zh40xBzwg5dcMjMLNOU0O/ +6wcbUfc5TwPBzjIBl06xvC2/GMrRuD0AQNvLl2CkqtJFBO/PGG8rZwKIXekHB87w +w2a4shDgGQmrrxgT0sQyN6psh9NwO9wK6ajt3ZMJdSbC6Eck4TGK5sAgmnxeUnHv +GBNtU1dofphwABR7gcrt6xG7bahCIHIkHRClJHWpUW6GgUS0cGdOdUy257EE8Kvn +4xq2QCKcnrLIXgXRMQG/C2vjJZx0UG/v/rjd2WgOt/xgh16TmGUpl2vBZ/xiuBCH +yv8AZhoL2Np7yOEFX4iJOyOFA2BSbaRffrrEVEBxD2YCroER2vvrAgYOwuAc+S74 +xUSw6h0vTy38YLleHawQ3a3f1nBF4m0Rqb4XEEONaSlyAujn3hM2InqER2CvMDH0 +DorVylk0eFcVa501zE02V5VZhTDvWzai1gJS4p6xfBjPJGd/GU5Ky5wXauDvF0PY +odjFpww3IY8eiDUE3Kdp45wFtooE4XwP7zR+dhMh3oeAv3kwk3rVol3SdCBhqECX +DCB9fGV+IkprTycOHlHHeFoFcmYTOxZTziNMiefBzc03VvQV8fWKTC4sA3k9s7AU +OzHNNVfj58ZQpbejuGBcCgNbW9dGDLzdtw+D7GZpTSoCUEvDJG5rJLw0eTxfGFgU +hNgNn5YKkRZRg8exP3gJyKxEJyu7rjhMaPWaA7gGtcR1gUc77c6UWq9Y6eRwsfHY +UrxozdSnBlqN0AOwLDWEuQYAAhDY8uYw0YqE2z7pI3wseN3BYh7jUJ1j5TblHEtS +nT3uBPneaIRWOIayg44FrZMnAANS1U2jvzesfNrIvFE/k7wG2gN2TSeF/jFV4geB +JzIbs7MGXQqQNV84f0EZLXQsTXbNoFX2xmBSg7AHjnPh/wAjKTmCD04gtBeXT95b +S9LNYls0OKIHzgZMRZw+gP6yuMIcX8/vWaggNh7MNHQXj8YKTqM2/wBMiCYOxdDz +1iwztYgVqDKXx3g3iMLoI5hY0UDk0UwPLA7BPGJip0QE5jIpHgz9vJ2YNNk5+D4y +ZVMQbaO1fXrOItEBpfBadY8FHuxZuOQDlwU4J3uDWGVgJViYceDHCnAVCRrWtYIa +g5CiRgQjUGTvdkV78taV0Dctgctup5BjDEseDA0hG6Q9CR8b6yZB13lwDo6uSrQB +e4yNQ2EJTb7eT7zTqUAEr7OWBbwujXY27MHYH8z1uzUvkdWTHKICagEE7oUAs6+a +cf5CU9emNG5KWi4S5jNcT5xIb3A8T1lpG+E/vJekdkTAKnYbdPjIaKgKtfP5xofJ +FjHaYICJ9o0urt4M50NPzbt+LEVxAQEC8Jq9zEpnZHC62QcPePtEe6ppmuO8Mo3a +hXf28Y2qAk+I9jJPWW25ADY3A7MNhZDgC3p0fOQ5qxR/P+MoUVBssxSfvDExxhMJ +H4F7zmocFwimg78WY9PU9SBfDBTK9EswTXoO8qhxQAi3lb8c/WbFOOdtVaE7Pzmz +V0K1b110Hxg6/voJDyeZzkSJQHn2mIpBRocx2c6us2CGRDAYxKga0VNOU7bQnzjC +FJkxCdpDyaWXpEFqCVKA/wDwid+sEywO197OM1SWTRd51Fqckhrke80lWgOZx1gN +kp0d8F9Z04hhCo+YYi8YqxvwuLNG3IiUdqc34zlTyqYHyn1wRNjGpJ+n9dfGM+iz +YHmoYccYvdgpC8OU3wpNklPvOcVypycfHOKSIaNOdSmusSRCzEFunjJ0aiEeCnGI +wCDsgum/xkwgo5HTOt+c5zNhLoBPcwLnuMgIq8auEL0kQA9B139Y6w7TT21fAPvN ++gj1clKn1hkEHP5w/g+c4SAmgbZDy7weXFGtrt+MNolgginP8Yl5O3N36MiokaEJ +dNmFxQmKUcmVtBTEIQB00UCwxGjCQNfQeHpyks4tH74wwaIaKefnP//EABQRAQAA +AAAAAAAAAAAAAAAAAJD/2gAIAQIBAT8AAD//xAAUEQEAAAAAAAAAAAAAAAAAAACQ +/9oACAEDAQE/AAA//9mJAlQEEwEKAD4CGwMFCwkIBwMFFQoJCAsFFgIDAQACHgEC +F4AWIQTj/yg5wEiyXAhN6+myaZXjECUFaAUCYJF1qwUJVjAeEAAKCRCyaZXjECUF +aH/mEACO/gg9l+jJRX7h0oCf4nQz0CvjhvjMCao/+Ynv59IvwjmdGyRdm0lmYruc ++F46MBbz+mSj0Y+p2gOoXQL95/SFdGoHmUaRmuXK4QlqHH9w77jfgRC8y0OK5pRc +c8NgMG2yA0Erip0HI4hsQrnU/lM6fEjk+fsAN1b27KgUSysambJnh4vqM+pmAB0g +Nzey0uIuHFEytTp3y9uNXlewFJ6seCePQ0MU8aWROMHZ6tUQq8M5UlIgVN09SGWs +y11g98T+J0sPfNWm+FV7kNJ+2DYydyTGqjEO7bOOFBKR7XQKwZHs+jh0t1/cAdla +Q+nsooOou3YNMZqdRXzS5zIIEKGYIMzfo8g/01Tf7W8uTPGSqL5MfggSWQRRHHQm +O2F19pLQr0AATagLPwSmWRh9lq6TLd8ytXMd7hsFut/7o1uhVKKcwBrqSWbwSIlD +w2+ZBGhck4J4WYokD/u685sO3dWJ2hk5kZ7nuUke/o979n9iyghHAIUysHqsUaT7 +LLiQbeX+JfPvqcObKI7WrLvDIQQHWu+rg4yWbeLgmqgT1sIlF2SRaU7HYRdqYBPS +bP1MhVwOPDkF2ZCYAxACdgezrp7Pg8hgEWY4RT7gxK/CoLisCVihORR8aezT4gCl +0aVSnOHE3mI7tWHYBRAnboU2Fgkm3fzzzbbpQv5uHlijX8BPVIkCIgQTAQoADAUC +VVJ0fwWDB4YfgAAKCRD8n7XhIU7pK6oRD/wKrbl0W51vDauCFCvfSqmzzcRNLFi7 +A8b9dQ0OnCQgoh9Vw0aKo/T4fQ7dPwprdiDuYToeUbDITnNKRf/0PNM75NEXL3ov +Wwon0PPJ3NdazJhnE9hoKX9VQI6gMzMk7CkpJiunC2gu2+9f3DOO2n/EeKKnZ6Wa +xS8Gh0uIO0aYhKPFWollaP3i92Jk+7ad71f5eb4XsDvz7V5CKxaCPJN37j7xSbbI +Ebxt03GhiavVeMuKBrIJKKdCq98dw+D3wqUWaL2gD+kILoRxNkT7aAWa1+7cxUKy +F9NB0lNaWN1Veqc+Qsr3/8eVI9JC+pPJ9xJgy70HG3emwYhkkKf1Lw4e5cnpjdfr +TNYbR0d0kdmjQz3ng0k7IkXveVdB82Cr6uAK0lUqFv6OqYiiP1/Bla6XvqtPw+so +jExpMp/SwEmMQdJWdbqZKwrypFf0kUtUbNcXHNMCm2ZxMO2ErnVpCVdVByOzalEH +pUt73yG6ygithiqX/gd6V2jDSvs0owOG3mfJyPdS6BMk9XWOZ1IPJXZOEQ+7l/f3 +ZX/svebZo+Kh1ublvfjcEa9LMmr6CMaJc73rp3uoW6ymB0ZnH4kkyWC8J+uQeMFT +nNKD9Y+ns+TvO6vkpw4cOJtr8V9hDpKjrpZiwiskL+ffFgW1mJdGLgpYczsKk1hv +/eZHnbABBRLTgokCPQQTAQoAJwUCVVEpMAIbAwUJEs/3gAULCQgHAwUVCgkICwUW +AgMBAAIeAQIXgAAKCRCyaZXjECUFaA7qD/9yFF0TPFy48/cfxM1B7OXSawVu/cv4 +YGGvQLVq9qce2G0uW3Ocjm/y49szQCWx1HbAVKdL52bpnA/C5JQGZv+GhSmAxDeY +QKkUneJUG5kt5u1ZqdQ8t1aLJwVri7CS77G15IMZ4Q6maTjcmXN8HC4lc1oM1U36 +brMvv8ZpGImPCMZ94baE0mdL7vaSluqRkOQt8rz8hu2JsZel7ou7yH3shJ0T6yJ8 +PozevsIlLvIRu/1A8j7HdYb1RA6qe8vD/Btmnw5LfsCSTLmEMlVHTRgtznuVYxe2 +UfYtiafMrWQxhHe/96EpzRv/ksU4uK5B66H/3SN3bOJvyEze4vImF5OhtGbelJQr +83vCOx7wCA3FozOosNF3asZGEOvSq2UY7E2+X0EnjQG+nqCMxE+D3m5sdtiGJtP4 +3/nvdYC3594htAKR7q+oTlasn3ap+QvGd1E1rX/zYMoBY03/4Sjy3AbQNoqHzj1T +x3ceGZJ6cUhX2gYHDQByObF9ae52B8mxgMrmh+TegtCAq4Q/wD4UJlOTYtt6Gt70 +b30GfdZjzwywG7xn/Gt/BopmHdg/8B7B1LRW3GjTJsWnGWG8jy7cNHIhWpSu5f7Z +leod1erypRxy26JttHiEkYBm7uOz9xAwslSXurIZBN7i2/+MxCfhFvNPsNmEWGBI +p+mPtWvWjVBherQhxYF1a2FzeiBMYW5nYSA8bHVrYXN6QHB5dGhvbi5vcmc+iQJU +BBMBCAA+AhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAFiEE4/8oOcBIslwITevp +smmV4xAlBWgFAmCRdasFCVYwHhAACgkQsmmV4xAlBWjeHg/9EhO5fNFc5ytoH1H8 +wWyYN83wq6ULKhzZJu30rbrkY/v4bz/hCkVZZGzwbgLpbXllyPPoc6gmYvSIDmL1 +cKdeWnlr4yWKMh2SGvWExvlFn8ShtIJGPykM/dRF4HgXSeeJy2VnLPUYFLKsabwU +lFM54ukZJ1e384rx4eLvWoNCsjGbHty0eXnr0lQ+5KzPIfD/ltqKyoTZp6FdJc5i +2Jl848/ck/DQkl21lhuJ/GlBoyMjbbEvj8+xDjFC2wbbFrrXSvNBMNTPqUgRbQ+a +ahHRnBUDOBhY3LhUd+NC6wTBLMs8n5f64XB8LMV2QzDwBgqAUXx/CnsxBP9kY5Vz +KxPsQYOxJiujlEvi5bC3Vj917n+mGXvcaokA8HvE4Jdn/5HyPpMjCKb1HU4D5U42 +k7U8WoFzi+H1nI0h36bbhhWJm9/feASwIGbpwHeFVNFEp0wWJS9s3BYIkFK7Kag5 +PyrcKzxlwGB8B8bKP39b2MYxyDjqSVLSVbFVKZLa0xsFyfzLR8y99sH7SxYlVwY+ +i6kbvCBu/y9q6tKZtS9faMUQLglNwchWNWBwesX+py7PbrNSLQkRaJz8yY0y4Ynx +hiDqolwIhOUer7dDjKs2EtA6ewdsih5gAQKgfZKl72v1G3VwjQ8ake/Brx5hrJNQ +l6En3VAHuJxBHyYDQiCYiG7eS8qJAlQEEwEIAD4WIQTj/yg5wEiyXAhN6+myaZXj +ECUFaAUCWmz8MwIbAwUJEs/3gAULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRCy +aZXjECUFaMmDD/9wqi/ZKfeCQ9H0Lrra9dIImCfNVu9+BNxPJReUWJlNwMOCy9hK +f/8LGCPPFKJJy0BCA+eBjEor/f8R9Pz6gIzAjSPlXhKWwS8qtMu7740mUMa4ofgo +vk8sikDbun0qGbgRIl++TOeTCt9pJnQak3xIsEg0sDs21gtbL4KZdpDHy3eGZPCW ++/+m4zoAkf2B3oWX7dHgTvCbKu1Lh3W2h2N8uMt5J6LXPu/65jI+XGoN7mJSji05 +GGPRXrjaoxtEv6x3Rp1xV5UmO7yWXhJbzzdDKcZz82Yrq+YpVfl3erNpNb7CVY0g +98cgiRDa9AMKvNFKQSM4iEUeDWNNK+qjYUFgcprOzbC3F3GhmigiYzjTH2FpIjVW +/TT4Pzd8Nvho4YgdD6UYZgssa2WUJpHUFpxGywv5jGxHZ0fbNMw23T3dobuOpm90 +AeT8VdSJyTWtOfUKX9HOjcUSp+kKaNDh/XjuNvKUHKWuh9yPeqlRRXTp+vyNLXif +WkW1aj1HUPAmI6G7dW7ctOAgTL2YbhBIyQiBFvGx4ydUuRRZjCR8m5185XOHRJHE +9S/uCKJqoBqI/MiikU8hheJzodgjxlaw2mFSaTMyJa0BJbeQTwNYFMC7LtTCTy8I +9o5PGAb5QfKqO6h/5jBrZdn4F5sS2r+0qvgaHdD/uOSh/Bb671oBWQXDIrQhxYF1 +a2FzeiBMYW5nYSA8bHVrYXN6QGVkZ2VkYi5jb20+iQJUBBMBCAA+AhsDBQsJCAcC +BhUKCQgLAgQWAgMBAh4BAheAFiEE4/8oOcBIslwITevpsmmV4xAlBWgFAmCRdasF +CVYwHhAACgkQsmmV4xAlBWh9/Q//b4iWPj7LOi2J/mqfebGczvMQgbuIu+V6gdO7 +2b0zfo/U4mT7EBw4p1hlsvkM536OSo2C5XxgApOkOPGSD5dofgh9jzF/cQ5uwmjk ++8ffYFOPnqdvvxB/gpoerTrVoKF7m0scwyw1/wE/KfNQS2E+q8bBMuaxoRgnuEEQ +auZ2ecqE0YZkLfr6HIJBQfIpqKvEbMmku209J7fd28zzO9Wsx/1APrFKBvIvvbZt +t/go2e4PeMoDGNhvOWARAHz0yy675mabI0B2iatqvQS0JTW94IfInUb3bZ9oGMsA +it0Mya8fm6K3o0o/l+adbce5cqpQXpuOAhSWRKuXRyayO5uyGH2W8Z7f9SFHEuEJ +mBAvMDSlK5vs2ufCbf+7Z8cjkkSyz0az5VV4l7CMICCCmE6nBb5GzT31p1X4ahP8 +oVdIgdJ1WlEmidfzUPvK/nbS+2HbJx7n8ZEmXIdULrq8Vq1QygmZT66pe9bx9Op4 +sIOEWXH8W3hyFDZvGpWSpVbEpUk6C8VCF8kkcykeQJp3kP4eA4R7dAzJ2QkvA1nt +AOkW8ma9iq9c34i173TP170D7Lw67SF7ZBB8mc3isvJ5dDybVCjqCD0FIRKcD9SJ +g1AF0Ay7ojSm11Fm2lZwgJR7dijzNgfXMEUwSQLuc3ADJ3gXq9Xu7oS1qEvMce5m +JylEx8qJAlQEEwEIAD4WIQTj/yg5wEiyXAhN6+myaZXjECUFaAUCXdbAzwIbAwUJ +Es/3gAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCyaZXjECUFaLZpD/4n1nL6 +cnDImUi66gwYCLl3WmVJNi99e65XEKmVaWPjJhlBetaPy4gEylurxvkKEJyj6doK +bjPByr5c1/muRMIoLj1AZVCuEFmKy5Czbaa8xQIuCclke7VjHN38v+Ft+E4I2tQp +0YVO9rFSp161J1DFetP3rnnPFtYO4tYh8AStoIzSE0p5/+q5BIcYR7AC5zR8JFdT +bsY2VQlL9t03hv+L7mfFN3pquH2qlnGpMT7/9HCu7eIX1PWfC1nDxYB+jrhMh8BS +qEsortPdTRjaZAlJTdWShYjNmllZq78xo+1K1usJ1tbsYWVqEkl2gRw69jnHCF95 +/qVlw8bt338o1ZZEvqgR6LYcuZ4xheAbfzUJlIbbcvO4YOqz722T2JCm+4AJ5WG+ +UWcxaHAh74UHYHUHfA84bRnRYbCyCo06sq9NDsufc1CeltDHz7ehYhbVy1jfcX+O +ON0C4j7xFiFmd2IMRJ+nFrbCTRULLo33MzVMQu/KZdXNgJI0n2pa4AP+9H6eQ8G6 +UMrDXVXLrNwgmnNsncLMiM4qkJgtJOZ00+z56AGRgoK3Nyud+CFvrQA5/EiF6vS8 +JsIN4gi95HxSPOI+UJX7Wl8alJtLH6VZjRu4zzOJT3H+Us9N9ZNpTOBQR3K8t7gZ ++trEPAEkQMG8tAvwxNMMpaMqu6sYTi4KX/6DwrQoxYF1a2FzeiBMYW5nYSA8bHVr +YXN6LmxhbmdhQHB5Zm91bmQub3JnPokCVAQTAQgAPhYhBOP/KDnASLJcCE3r6bJp +leMQJQVoBQJixGEpAhsDBQlWMB4QBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJ +ELJpleMQJQVoUbUP/RuyctMWcUju01mrrRlLDECiu/i8Zxhi0Dr+8cs/LvIsviK0 +82yg/B0BWjFDTpUXjrV2xMK5pV7nXA/K+14P2hFM4J0URiaQrL5+DokAPd72aZwB +IhBW5lhcZuxFn7lqgM2tHXLa/La2705sPqNEHdw6s9ISRIK18due4CCGmDhUuamu +T5IRAYifG5ksdFSQWJeOq7z+dc0+qAAty22LcQlZCnoOxZuypXESzFMlTpS3SFcc +3unqQK6zujZeEnGA0adViOGADMT+qFUdMi6uXI8JSY37gt31qNN1sxL8bbUV0aLb +YcHDcacsawB0A5Gif9IPKONwM1lexDzI/6pHzZ04VA6XsLTuHi0EjoltqR1entJr +Uzq40UfzFfnUOwucKnbDgenOne2EKBqSCOj8Aylg4w3afw5vv+xqaUrFl0ITDc1p +98ZBGOCxwnPvD/Vhj7s2qNl5I9j4Bto6HDL7wNDjA/B5gsSAxHyOBtITl3Z21SCz +iaA07f0KgDDTdnDV3LYKzUibOTvsrYMcegJ7gdRi/V+wpDE02LNH06UdXAM+geBQ +UDTsHdsmVOeIi+axjwz3cWmgxCAanjEtoq9qerCaVnBTTHqrSc4SvSXNfgXFmiJr +8R/jdSMmha9v2Eujqn5uHS/njOYKvOl/LlDT+WX64WkMgDJefoDysIAEdS0btCHF +gXVrYXN6IExhbmdhIDxycGxrdHJAcnBsa3RyLmNvbT6JAlQEEwEIAD4WIQTj/yg5 +wEiyXAhN6+myaZXjECUFaAUCYxY98gIbAwUJVjAeEAULCQgHAgYVCgkICwIEFgID +AQIeAQIXgAAKCRCyaZXjECUFaCZfD/9wKIaUvvWsaZT4dq0zwnS03Q7XqNwlXYQh +LQ8t5WzKVr5QSQFp9yARGBVfLjyJ4Tfwc/M3HEkAQMAF8umGMp41ESI1/6wma6o6 +IwgF13CFUO2Mt6xJ0SyZlxz5q1XY71hgOYPa7rS+8OwBIXCMbONwLI/0y2Gxg+t7 +eQbpqmE3/DHpHb8EhEl0odyXh5vzxFa3jNsOudeJbE/oVbmA2KtPEw68wmg8Q97a +qSbrLhP2tXJ+tN9H+p3+2D1tF1T1eC+hYSMe90LQwOYB/aD+MyMj3ai06RdDGmP6 +V3DvfKfLZPWFC+2RRmdenPsZB5TrJX6rjHYTo4qcvG2n6yAoxy7LvDwYHHJDkjax +VQHsGVj/rnBflzgEE2hKWmKFSfJ5iTVeFW75PMtIJAIqbAd9R9U+QzLWprkk92jl +usde/qOzjSDLG938xHtPl/W1BEwYCWCmu3cc8YiIZL2+Ig/1m8tnI/i65v70qxOX +zJT4HN0aZzyHmaM9JIduMm4geTSFLAIfT+Xh53a/ugzmpwSQhkCPSpr/CSj0tWKL +p+UQOojstrwSN745bhujUMl0zpedw6JBd3Mehj54ZR5E3yP8DYpVb/531xuZGpGO +okc2sC7AQj+KsOOwlss15Pp5PcG5vHzEsViW1k2hzfJWyuXCIviex1nsbRCQLIYy +xte6FM9RirkCDQRVUSdJARAAt+LOfnsgS/UUBHlxPITQXI39A58YEHstzEjK90kl +WtLvrLPBrqklWBqWcF8QdBeiSsi/qC/Ybp5GnJ8D/QUjCWWv/gIyB6LJ7Wxj+0v1 +8FNYbVXTVm8cI9ZqG76VDCY49xbvlr5fbqiZr1fryA/XdA5co9L0avFzrqF/dl7n +LYWAfRoNgF0it5t6RMWcQ8Sat7VV0S9DtBW+PXIIcnvuSMwWANSPIzWKydT3ZTq0 +MvNs82yMk4kEc3uYQLcpF7Mw7ZT7cuB5uj9SbODAeS2dmcvWhkbaoE++CltEsdEn +qWM83rD6ABb+dIm4d2Zak+/IKQB9MOPgd3h3+g5FSJS87krZCq3NpO4NCe3jx55y +YeJktRjB+g+yqvoH3Es4SUfYrW4PajWoG3esC6b5+DjGacLupjEbc9vSr0P8+nOm +jAADzuRbMvQe6hUqeEsflIeOJ4nUsgR7Hr0h4qgsXuASRnxNiYh6cEAwN1YYXyO4 +sSETT7cbwpy4qVx5SVrNzt4wITvH1nz3C0d+mR2w74F/QgoZN9quOxWcKx0e0yh8 +Fq1pQn5LntvuIdq9K1RGNSKVz1SgzuiLNNiuqKOyuksrJMpe9qv65NiCUkGcG9+L +PI00bqs/nGiL6yF8hRFG/q3To4o1v9AShmu1c1hBguzSOYrNH0qgO8jmgDSJNBrm +3R8AEQEAAYkCJQQYAQoADwUCVVEnSQIbDAUJEs/3gAAKCRCyaZXjECUFaDoZD/9Y +kQgWlkn/MjQ2aT94DIExfGMAF36tXa/3g3UABEo334IMZ2xSYP08y5RuGwvvY1/N +Pgf82KszkY+Z1rbwoOpc4rcl2rXYg45nPnmyM3dHC2YZufB/SxFFZKEkLbZbRjhB +sUPTSPuaxed9Xl8tXnW+Wv+pAD5DZuuMMvTqENhty/Au16kVAxyI+OOqijKtfKLp +Oert0VTp9zB/VXgBZC3cDs6qSaZymNHRvRgczWYQA7U4HZvn9L2gFjmPnFaLCapx +MH6UHtTS27eEHuWJaBL7XOhqEKc6P35xRKPYH6pJpRbEbcr11vhOIAT2rqBSj+av +Q98S3U8ST9hkUd5R0Vao43wf/6ddZyvqFmP2BXhyejutZhR3kbXFY8WoqsstFjxk +go840G7gtq5ZgA111bEq+4aEA2R0xOdTfjpPUZ9KuOdqCZlLBAcK+LikLJk872GU +WQCxU/QZGRGYHaxJ4Gz/3A2DN5l2zXwcbEbP2DGadiDgYlVfjnZLdSOLSCoyuWHL ++s/V/4uY4HUVVkBLZEsd6Wh81vgUTdFfnwsnCMRCT9aWo2jOvg/KGtH6hWIHAJl3 +menwYOd9VTrjcFnWr3pfL0qsf44pOG/EkuMoCvjDTBRRkyAzzxLlb9OygUqtRQq2 +wyssv8SmSMGlLrfee+7yz1F9N6mVsuyl21KxQV8PGw== +=baTu +-----END PGP PUBLIC KEY BLOCK----- diff --git a/python3.10.spec b/python3.10.spec index e4e3677..a1744fe 100644 --- a/python3.10.spec +++ b/python3.10.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}.13 +%global general_version %{pybasever}.14 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 6%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -261,8 +261,13 @@ BuildRequires: python3-rpm-generators Source0: %{url}ftp/python/%{general_version}/Python-%{upstream_version}.tar.xz Source1: %{url}ftp/python/%{general_version}/Python-%{upstream_version}.tar.xz.asc -# The release manager for Python 3.10 is pablogsal -Source2: https://keybase.io/pablogsal/pgp_keys.asc +# The release manager for Python 3.10 is pablogsal, +# but Python 3.10.14 was signed by Łukasz Langa. +# pgp_keys_combined.asc contains keys of both release managers. +# Upstream issue: https://github.com/python/cpython/issues/117053 +# https://keybase.io/pablogsal/pgp_keys.asc +# https://keybase.io/ambv/pgp_keys.asc +Source2: pgp_keys_combined.asc # A simple script to check timestamps of bytecode files # Run in check section with Python that is currently being built @@ -329,13 +334,6 @@ Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-par # 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 -# 00422 # a353cebef737c41420dc7ae2469dd657371b8881 -# gh-115133: Fix tests for XMLPullParser with Expat 2.6.0 -# -# Feeding the parser by too small chunks defers parsing to prevent -# CVE-2023-52425. Future versions of Expat may be more reactive. -Patch422: 00422-gh-115133-fix-tests-for-xmlpullparser-with-expat-2-6-0.patch - # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1609,6 +1607,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Mar 20 2024 Tomáš Hrnčiar - 3.10.14-1 +- Update to 3.10.14 + * Wed Feb 28 2024 Charalampos Stratakis - 3.10.13-6 - Fix tests for XMLPullParser with Expat 2.6.0 diff --git a/sources b/sources index b4b0734..9acf607 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.13.tar.xz) = 7579772e501486b2b07f78142082dee1e99c7643640098860ac0cf2ca87daf7588b0c00b1db1960146b37f56a6ed98fd08297c25c9a19b612cf6e6a258984da8 -SHA512 (Python-3.10.13.tar.xz.asc) = 3083e66f8d26128302dc77a0c6ba3bfefc4229928a1bbd06460f2fec2421188bd30d493e3bce138cde1fed1df206e1dda04912b9f43a0b81229f1e69135e3a7f +SHA512 (Python-3.10.14.tar.xz) = adee638aeca898743da4b8245c0fa1e9b94b516f22e716e60c99038f0bb3dcbf726317aa86656404be1719b5a7c58eb09533720ebc0badbb04bd9a534dd48fef +SHA512 (Python-3.10.14.tar.xz.asc) = 821046b8eb559c3ef800f26739c995e7a71469a1e765ee7d516690236e16d2637ada7b2f9535b8c0dceaacf243e7b059f6f106b4a25faae365aa2099d1ff538c From b3ea7e1f7dcb3beb640a6619b8834cd53b611233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 17 Apr 2024 22:58:28 +0000 Subject: [PATCH 077/112] Require expat >= 2.6 to prevent errors when creating venvs with older expat The code in CPython uses XML_SetReparseDeferralEnabled when expat is >= 2.6 during the build. However, when users upgrade Python independently on the expat package, they may have expat 2.5 installed and see errors like: $ python3.1X -m venv venv Error: Command '['venv/bin/python3.1X', '-m', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1. $ venv/bin/python3.1X -m ensurepip --upgrade --default-pip Traceback (most recent call last): ... File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_internal/commands/install.py", line 15, in from pip._internal.cli.req_command import ( ...<3 lines>... ) File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_internal/cli/req_command.py", line 21, in from pip._internal.index.package_finder import PackageFinder File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_internal/index/package_finder.py", line 30, in from pip._internal.req import InstallRequirement File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_internal/req/__init__.py", line 8, in from .req_install import InstallRequirement File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_internal/req/req_install.py", line 40, in from pip._internal.operations.install.wheel import install_wheel File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_internal/operations/install/wheel.py", line 39, in from pip._vendor.distlib.scripts import ScriptMaker File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_vendor/distlib/scripts.py", line 16, in from .compat import sysconfig, detect_encoding, ZipFile File "/tmp/.../pip-24.0-py3-none-any.whl/pip/_vendor/distlib/compat.py", line 81, in import xmlrpc.client as xmlrpclib File "/usr/lib64/python3.1X/xmlrpc/client.py", line 138, in from xml.parsers import expat File "/usr/lib64/python3.1X/xml/parsers/expat.py", line 4, in from pyexpat import * ImportError: /usr/lib64/python3.1X/lib-dynload/pyexpat.cpython-31X-x86_64-linux-gnu.so: undefined symbol: XML_SetReparseDeferralEnabled Traceback (most recent call last): ... subprocess.CalledProcessError: Command '['venv/bin/python3.1X', '-W', 'ignore::DeprecationWarning', '-c', '\nimport runpy\nimport sys\nsys.path = [\'/tmp/.../pip-24.0-py3-none-any.whl\'] + sys.path\nsys.argv[1:] = [\'install\', \'--no-cache-dir\', \'--no-index\', \'--find-links\', \'/tmp/...\', \'--upgrade\', \'pip\']\nrunpy.run_module("pip", run_name="__main__", alter_sys=True)\n']' returned non-zero exit status 1. Thanks to Markus Falb for discovering this problem. https://lists.fedoraproject.org/archives/list/python-devel@lists.fedoraproject.org/thread/7XHGWHBQDNFKNGSZTP44SSD6PQKZPG6C/ --- python3.10.spec | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index a1744fe..df16825 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -192,7 +192,8 @@ BuildRequires: bluez-libs-devel BuildRequires: bzip2 BuildRequires: bzip2-devel BuildRequires: desktop-file-utils -BuildRequires: expat-devel +# See the runtime requirement in the -libs subpackage +BuildRequires: expat-devel >= 2.6 BuildRequires: findutils BuildRequires: gcc-c++ @@ -479,6 +480,14 @@ Recommends: (%{pkgname}-tkinter%{?_isa} = %{version}-%{release} if tk%{?_isa}) # The zoneinfo module needs tzdata Requires: tzdata +# The requirement on libexpat is generated, but we need to version it. +# When built with expat >= 2.6, but installed with older expat, we get: +# ImportError: /usr/lib64/python3.X/lib-dynload/pyexpat.cpython-....so: +# undefined symbol: XML_SetReparseDeferralEnabled +# This breaks many things, including python -m venv. +# Other subpackages (like -debug) also need this, but they all depend on -libs. +Requires: expat >= 2.6 + # Since patch 251 changed from distutils to sysconfig, pip needed to be adapted # The previous versions could cause serious bugs during `sudo pip install --upgrade ...` # Better safe than sorry @@ -1607,6 +1616,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Apr 17 2024 Miro Hrončok - 3.10.14-2 +- Require expat >= 2.6 to prevent errors when creating venvs with older expat + * Wed Mar 20 2024 Tomáš Hrnčiar - 3.10.14-1 - Update to 3.10.14 From f7d93eee1878711a65574c6ad46fc957b9e1ecf9 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 19 Jul 2024 17:26:02 +0000 Subject: [PATCH 078/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index df16825..d839f00 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -1616,6 +1616,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jul 19 2024 Fedora Release Engineering - 3.10.14-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Wed Apr 17 2024 Miro Hrončok - 3.10.14-2 - Require expat >= 2.6 to prevent errors when creating venvs with older expat From 67b71083facd7607a7f04b067c017f82fc477287 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 23 Jul 2024 13:23:31 +0200 Subject: [PATCH 079/112] Require systemtap-sdt-devel for sys/sdt.h --- python3.10.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index d839f00..c9283f0 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python-2.0.1 @@ -236,6 +236,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) @@ -1616,6 +1617,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Jul 23 2024 Lumír Balhar - 3.10.14-4 +- Require systemtap-sdt-devel for sys/sdt.h + * Fri Jul 19 2024 Fedora Release Engineering - 3.10.14-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild From 6d6290fa95ba6b1e1242c107929643a068ba8689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Mon, 9 Sep 2024 10:54:57 +0200 Subject: [PATCH 080/112] Update to 3.10.15 --- ...-addresses-in-email-parseaddr-111116.patch | 500 ------------------ ...h-non-int-suffix-gh-112771-gh-112774.patch | 66 --- python3.10.spec | 22 +- sources | 4 +- 4 files changed, 7 insertions(+), 585 deletions(-) delete mode 100644 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch delete mode 100644 00419-gh-112769-test_zlib-fix-comparison-of-zlib_runtime_version-with-non-int-suffix-gh-112771-gh-112774.patch 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 7d2a813..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 0e266b6a45..6723dc4f13 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 cfdfeb3f1a..9522341fab 100644 ---- a/Lib/email/utils.py -+++ b/Lib/email/utils.py -@@ -48,6 +48,7 @@ - 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): -@@ -205,16 +321,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 8b16cca9bf..5b19bb38f6 100644 ---- a/Lib/test/test_email/test_email.py -+++ b/Lib/test/test_email/test_email.py -@@ -16,6 +16,7 @@ - - import email - import email.policy -+import email.utils - - from email.charset import Charset - from email.generator import Generator, DecodedGenerator, BytesGenerator -@@ -3288,15 +3289,154 @@ def test_getaddresses(self): - [('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""" -@@ -3485,6 +3625,54 @@ def test_mime_classes_policy_argument(self): - 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 1e718a6..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 cb0610837b..98cac4fb91 100644 ---- a/Lib/test/test_zlib.py -+++ b/Lib/test/test_zlib.py -@@ -19,6 +19,20 @@ - '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): -@@ -445,9 +459,8 @@ def test_flushes(self): - 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 -@@ -776,16 +789,7 @@ def test_large_unconsumed_tail(self, size): - - 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/python3.10.spec b/python3.10.spec index c9283f0..9841543 100644 --- a/python3.10.spec +++ b/python3.10.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}.14 +%global general_version %{pybasever}.15 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -321,21 +321,6 @@ Patch251: 00251-change-user-install-location.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00415 # 9ca4533e0b4a03d919953017026f66c6a060756e -# [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. -Patch415: 00415-cve-2023-27043-gh-102988-reject-malformed-addresses-in-email-parseaddr-111116.patch - -# 00419 # f13682530cc7e4daec2e40acd56508846fdd3aad -# 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". -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 ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1617,6 +1602,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Sep 09 2024 Tomáš Hrnčiar - 3.10.15-1 +- Update to 3.10.15 + * Tue Jul 23 2024 Lumír Balhar - 3.10.14-4 - Require systemtap-sdt-devel for sys/sdt.h diff --git a/sources b/sources index 9acf607..1859df7 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.14.tar.xz) = adee638aeca898743da4b8245c0fa1e9b94b516f22e716e60c99038f0bb3dcbf726317aa86656404be1719b5a7c58eb09533720ebc0badbb04bd9a534dd48fef -SHA512 (Python-3.10.14.tar.xz.asc) = 821046b8eb559c3ef800f26739c995e7a71469a1e765ee7d516690236e16d2637ada7b2f9535b8c0dceaacf243e7b059f6f106b4a25faae365aa2099d1ff538c +SHA512 (Python-3.10.15.tar.xz) = 3c0396b2dae1521315a9b5ce9ad4ab6ede385447922fceb00ea3df75bfd79cb547b9380e936d83c9c1b964e38e16d70e34aec39f4c292853a032407bb6a58063 +SHA512 (Python-3.10.15.tar.xz.asc) = 0cac9b78649330a2a35a835d45e4a8a111db45943cc0ae0d24f5d9e03a058b4b739fe43d6cd1aee481dcd415a57820bf875996fa60b81d4d5911588db5adad70 From cdabc2abe703488c5d24475c2a876b9b845fe613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 9 Sep 2024 16:10:38 +0200 Subject: [PATCH 081/112] Skip test_sendfile_close_peer_in_the_middle_of_receiving on ppc64le Reported upstream https://github.com/python/cpython/issues/123384 Which was a duplicate of https://github.com/python/cpython/issues/120226 The test is fixed on the main branch, but skipping is easier than backporting. The failure occurs with Kernel 6.10.x even when Python is built with an older Kernel. --- python3.10.spec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index 9841543..d302ccf 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -1095,6 +1095,8 @@ CheckPython() { # test_distutils # distutils.tests.test_bdist_rpm tests fail when bootstraping the Python # package: rpmbuild requires /usr/bin/pythonX.Y to be installed + # 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} @@ -1103,6 +1105,9 @@ CheckPython() { %ifarch %{mips64} -x test_ctypes \ %endif + %ifarch ppc64le + -i test_sendfile_close_peer_in_the_middle_of_receiving \ + %endif echo FINISHED: CHECKING OF PYTHON FOR CONFIGURATION: $ConfName From 5c73fd0f8e44b537b1291b9f1894bb5f7eb9143b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 11 Sep 2024 20:20:50 +0200 Subject: [PATCH 082/112] Fix ThreadedVSOCKSocketStreamTest --- ...treamtest-gh-119465-gh-119479-119484.patch | 66 +++++++++++++++++++ python3.10.spec | 16 ++++- 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch diff --git a/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch b/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch new file mode 100644 index 0000000..7e1c35d --- /dev/null +++ b/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Fri, 24 May 2024 01:23:55 +0200 +Subject: [PATCH] 00438: Fix ThreadedVSOCKSocketStreamTest (GH-119465) + (GH-119479) (#119484) + +Fix ThreadedVSOCKSocketStreamTest: if get_cid() returns the host +address or the "any" address, use the local communication address +(loopback): VMADDR_CID_LOCAL. + +On Linux 6.9, apparently, the /dev/vsock device is now available but +get_cid() returns VMADDR_CID_ANY (-1). + +(cherry picked from commit c750061047ee520d8299334df4b112fd983d7e48) + +Co-authored-by: Victor Stinner +(cherry picked from commit e94dbe4ed83460f18bd72563c5f09f6cdc71f604) + +Co-authored-by: Victor Stinner +--- + Lib/test/test_socket.py | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py +index 4c8f55d3e1..2acf608123 100644 +--- a/Lib/test/test_socket.py ++++ b/Lib/test/test_socket.py +@@ -41,6 +41,7 @@ + # test unicode string and carriage return + MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf-8') + ++VMADDR_CID_LOCAL = 1 + VSOCKPORT = 1234 + AIX = platform.system() == "AIX" + +@@ -124,8 +125,8 @@ def _have_socket_qipcrtr(): + + def _have_socket_vsock(): + """Check whether AF_VSOCK sockets are supported on this host.""" +- ret = get_cid() is not None +- return ret ++ cid = get_cid() ++ return (cid is not None) + + + def _have_socket_bluetooth(): +@@ -487,8 +488,6 @@ def clientTearDown(self): + @unittest.skipIf(fcntl is None, "need fcntl") + @unittest.skipUnless(HAVE_SOCKET_VSOCK, + 'VSOCK sockets required for this test.') +-@unittest.skipUnless(get_cid() != 2, +- "This test can only be run on a virtual guest.") + class ThreadedVSOCKSocketStreamTest(unittest.TestCase, ThreadableTest): + + def __init__(self, methodName='runTest'): +@@ -509,6 +508,9 @@ def clientSetUp(self): + self.cli = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM) + self.addCleanup(self.cli.close) + cid = get_cid() ++ if cid in (socket.VMADDR_CID_HOST, socket.VMADDR_CID_ANY): ++ # gh-119461: Use the local communication address (loopback) ++ cid = VMADDR_CID_LOCAL + self.cli.connect((cid, VSOCKPORT)) + + def testStream(self): diff --git a/python3.10.spec b/python3.10.spec index d302ccf..8623a54 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -321,6 +321,17 @@ Patch251: 00251-change-user-install-location.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch +# 00438 # 640f507108d102da99fa2f39d268a43f86c97acb +# Fix ThreadedVSOCKSocketStreamTest (GH-119465) (GH-119479) (#119484) +# +# Fix ThreadedVSOCKSocketStreamTest: if get_cid() returns the host +# address or the "any" address, use the local communication address +# (loopback): VMADDR_CID_LOCAL. +# +# On Linux 6.9, apparently, the /dev/vsock device is now available but +# get_cid() returns VMADDR_CID_ANY (-1). +Patch438: 00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1607,6 +1618,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Sep 11 2024 Miro Hrončok - 3.10.15-2 +- Fix ThreadedVSOCKSocketStreamTest + * Mon Sep 09 2024 Tomáš Hrnčiar - 3.10.15-1 - Update to 3.10.15 From 9af4582cf940c5e79027a4ccea9c8f33c53b4428 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 5 Dec 2024 00:54:17 +0100 Subject: [PATCH 083/112] Update to 3.10.16 Security fix for CVE-2024-9287 Resolves: rhbz#2321654 --- python3.10.spec | 9 +++++++-- sources | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 8623a54..2a9e28a 100644 --- a/python3.10.spec +++ b/python3.10.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}.15 +%global general_version %{pybasever}.16 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -1618,6 +1618,11 @@ CheckPython optimized # ====================================================== %changelog +* Wed Dec 04 2024 Charalampos Stratakis - 3.10.16-1 +- Update to 3.10.16 +- Security fix for CVE-2024-9287 +Resolves: rhbz#2321654 + * Wed Sep 11 2024 Miro Hrončok - 3.10.15-2 - Fix ThreadedVSOCKSocketStreamTest diff --git a/sources b/sources index 1859df7..fe5766d 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.15.tar.xz) = 3c0396b2dae1521315a9b5ce9ad4ab6ede385447922fceb00ea3df75bfd79cb547b9380e936d83c9c1b964e38e16d70e34aec39f4c292853a032407bb6a58063 -SHA512 (Python-3.10.15.tar.xz.asc) = 0cac9b78649330a2a35a835d45e4a8a111db45943cc0ae0d24f5d9e03a058b4b739fe43d6cd1aee481dcd415a57820bf875996fa60b81d4d5911588db5adad70 +SHA512 (Python-3.10.16.tar.xz) = a6b004974db93f21590f00b9b1a569dfd8c3e334f8c6a8eb8997dec5646fa4515cfc02a7dabea9e4f75f908938dc64333ce4899b9a26aff97f9ffcb027fa2bca +SHA512 (Python-3.10.16.tar.xz.asc) = 18032fdb60a022d6381b1137789ada1c4bb198049616ed158fb548e728dd1fb95d116a86c41c852ca2acc9127baf3cdd9644a1e2df90ae9c3ffcd66eabf454d6 From 10df3778231e849edb5856da80edef71d199b607 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 18 Jan 2025 21:08:05 +0000 Subject: [PATCH 084/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 2a9e28a..ee9c961 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -1618,6 +1618,9 @@ CheckPython optimized # ====================================================== %changelog +* Sat Jan 18 2025 Fedora Release Engineering - 3.10.16-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + * Wed Dec 04 2024 Charalampos Stratakis - 3.10.16-1 - Update to 3.10.16 - Security fix for CVE-2024-9287 From df15baee4759bd389c5b685ca502f489845b7da6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Sat, 1 Feb 2025 19:56:54 +0100 Subject: [PATCH 085/112] Add explicit BR: libxcrypt-devel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- python3.10.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index ee9c961..0a4cb85 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -211,6 +211,7 @@ BuildRequires: libnsl2-devel BuildRequires: libtirpc-devel BuildRequires: libGL-devel BuildRequires: libuuid-devel +BuildRequires: libxcrypt-devel BuildRequires: libX11-devel BuildRequires: make BuildRequires: mpdecimal-devel @@ -1618,6 +1619,9 @@ CheckPython optimized # ====================================================== %changelog +* Sat Feb 01 2025 Björn Esser - 3.10.16-3 +- Add explicit BR: libxcrypt-devel + * Sat Jan 18 2025 Fedora Release Engineering - 3.10.16-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild From dfe7d5095710e43837ada19faf7d1767c6e114f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 3 Feb 2025 11:13:44 +0000 Subject: [PATCH 086/112] Ensure this package is built with Tk 8 - Fixes: rhbz#2337757 --- python3.10.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 0a4cb85..056d369 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -225,9 +225,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} From ee2c642d121163c701921884080baa51d0fba9ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 6 Feb 2025 12:04:28 +0100 Subject: [PATCH 087/112] Rebuilt with mpdecimal 4.0.0 --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 056d369..06ef873 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python-2.0.1 @@ -1619,6 +1619,9 @@ CheckPython optimized # ====================================================== %changelog +* Thu Feb 06 2025 Miro Hrončok - 3.10.16-4 +- Rebuilt with mpdecimal 4.0.0 + * Sat Feb 01 2025 Björn Esser - 3.10.16-3 - Add explicit BR: libxcrypt-devel From df9826a90ed6c7ee343c716ddac9440ca7998bae Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Mon, 10 Feb 2025 23:40:17 +0100 Subject: [PATCH 088/112] Security fix for CVE-2025-0938 Fixes: rhbz#2343276 --- ...treamtest-gh-119465-gh-119479-119484.patch | 2 +- ...-and-in-domain-names-for-parsed-urls.patch | 119 ++++++++++++++++++ python3.10.spec | 10 +- 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch diff --git a/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch b/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch index 7e1c35d..01a308d 100644 --- a/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch +++ b/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch @@ -23,7 +23,7 @@ Co-authored-by: Victor Stinner 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py -index 4c8f55d3e1..2acf608123 100644 +index 0050298b41..12b90dcacb 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -41,6 +41,7 @@ diff --git a/00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch b/00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch new file mode 100644 index 0000000..5d005cb --- /dev/null +++ b/00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch @@ -0,0 +1,119 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Fri, 31 Jan 2025 11:41:34 -0600 +Subject: [PATCH] 00450: CVE-2025-0938: Disallow square brackets ([ and ]) in + domain names for parsed URLs + +Co-authored-by: Peter Bierma +--- + Lib/test/test_urlparse.py | 37 ++++++++++++++++++- + Lib/urllib/parse.py | 20 +++++++++- + ...-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | 4 ++ + 3 files changed, 58 insertions(+), 3 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst + +diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py +index f2ffc452e5..280644ef0b 100644 +--- a/Lib/test/test_urlparse.py ++++ b/Lib/test/test_urlparse.py +@@ -1149,16 +1149,51 @@ def test_invalid_bracketed_hosts(self): + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query') + self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]/') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix/') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]?') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix?') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]/') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix/') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]?') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix?') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a1') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a1') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:1a') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:1a') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:/') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:?') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@prefix.[v6a.ip]') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@[v6a.ip].suffix') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip]') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip[') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip].suffix') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip[suffix') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip') ++ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[suffix') + + def test_splitting_bracketed_hosts(self): +- p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query') ++ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]:1234/path?query') + self.assertEqual(p1.hostname, 'v6a.ip') + self.assertEqual(p1.username, 'user') + self.assertEqual(p1.path, '/path') ++ self.assertEqual(p1.port, 1234) + p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query') + self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test') + self.assertEqual(p2.username, 'user') + self.assertEqual(p2.path, '/path') ++ self.assertIs(p2.port, None) + p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query') + self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test') + self.assertEqual(p3.username, 'user') +diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py +index 07e3248504..e1ee36d98e 100644 +--- a/Lib/urllib/parse.py ++++ b/Lib/urllib/parse.py +@@ -442,6 +442,23 @@ def _checknetloc(netloc): + raise ValueError("netloc '" + netloc + "' contains invalid " + + "characters under NFKC normalization") + ++def _check_bracketed_netloc(netloc): ++ # Note that this function must mirror the splitting ++ # done in NetlocResultMixins._hostinfo(). ++ hostname_and_port = netloc.rpartition('@')[2] ++ before_bracket, have_open_br, bracketed = hostname_and_port.partition('[') ++ if have_open_br: ++ # No data is allowed before a bracket. ++ if before_bracket: ++ raise ValueError("Invalid IPv6 URL") ++ hostname, _, port = bracketed.partition(']') ++ # No data is allowed after the bracket but before the port delimiter. ++ if port and not port.startswith(":"): ++ raise ValueError("Invalid IPv6 URL") ++ else: ++ hostname, _, port = hostname_and_port.partition(':') ++ _check_bracketed_host(hostname) ++ + # Valid bracketed hosts are defined in + # https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/ + def _check_bracketed_host(hostname): +@@ -505,8 +522,7 @@ def urlsplit(url, scheme='', allow_fragments=True): + (']' in netloc and '[' not in netloc)): + raise ValueError("Invalid IPv6 URL") + if '[' in netloc and ']' in netloc: +- bracketed_host = netloc.partition('[')[2].partition(']')[0] +- _check_bracketed_host(bracketed_host) ++ _check_bracketed_netloc(netloc) + if allow_fragments and '#' in url: + url, fragment = url.split('#', 1) + if '?' in url: +diff --git a/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst +new file mode 100644 +index 0000000000..bff1bc6b0d +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst +@@ -0,0 +1,4 @@ ++When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` host ++parsing would not reject domain names containing square brackets (``[`` and ++``]``). Square brackets are only valid for IPv6 and IPvFuture hosts according to ++`RFC 3986 Section 3.2.2 `__. diff --git a/python3.10.spec b/python3.10.spec index 06ef873..15b0da5 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 5%{?dist} License: Python-2.0.1 @@ -333,6 +333,10 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # get_cid() returns VMADDR_CID_ANY (-1). Patch438: 00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch +# 00450 # 4ab8663661748eb994c09e4ae89f59eb84c5d3ea +# CVE-2025-0938: Disallow square brackets ([ and ]) in domain names for parsed URLs +Patch450: 00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1619,6 +1623,10 @@ CheckPython optimized # ====================================================== %changelog +* Mon Feb 10 2025 Charalampos Stratakis - 3.10.16-5 +- Security fix for CVE-2025-0938 +- Fixes: rhbz#2343276 + * Thu Feb 06 2025 Miro Hrončok - 3.10.16-4 - Rebuilt with mpdecimal 4.0.0 From aceb601ce349562dce8140241fec105d0b3ecdee Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Tue, 1 Apr 2025 01:44:48 +0200 Subject: [PATCH 089/112] Properly apply exported CFLAGS for dtrace/systemtap builds Fixes: rhbz#2356303 --- ...d-cflags-for-dtrace-systemtap-builds.patch | 52 +++++++++++++++++++ python3.10.spec | 18 ++++++- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch 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..359d9ac --- /dev/null +++ b/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch @@ -0,0 +1,52 @@ +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: [PATCH] 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 fa99dd86c4..e9ba702a5c 100644 +--- a/Makefile.pre.in ++++ b/Makefile.pre.in +@@ -1001,7 +1001,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 $@ +@@ -1011,7 +1011,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/python3.10.spec b/python3.10.spec index 15b0da5..221d3c6 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 5%{?dist} +Release: 6%{?dist} License: Python-2.0.1 @@ -337,6 +337,18 @@ Patch438: 00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.pat # CVE-2025-0938: Disallow square brackets ([ and ]) in domain names for parsed URLs Patch450: 00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch +# 00452 # eb11d070c5af7d1b5e47f4e02186152d08eaf793 +# 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. +Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1623,6 +1635,10 @@ CheckPython optimized # ====================================================== %changelog +* Mon Mar 31 2025 Charalampos Stratakis - 3.10.16-6 +- Properly apply exported CFLAGS for dtrace/systemtap builds +- Fixes: rhbz#2356303 + * Mon Feb 10 2025 Charalampos Stratakis - 3.10.16-5 - Security fix for CVE-2025-0938 - Fixes: rhbz#2343276 From a48837eb4a4e05c6ed544861e46c97abfd4f4a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 9 Apr 2025 09:54:55 +0200 Subject: [PATCH 090/112] Update to 3.10.17 Patches 438 and 450 merged upstream. --- ...treamtest-gh-119465-gh-119479-119484.patch | 66 ---------- ...-and-in-domain-names-for-parsed-urls.patch | 119 ------------------ python3.10.spec | 22 +--- sources | 4 +- 4 files changed, 7 insertions(+), 204 deletions(-) delete mode 100644 00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch delete mode 100644 00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch diff --git a/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch b/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch deleted file mode 100644 index 01a308d..0000000 --- a/00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Miss Islington (bot)" - <31488909+miss-islington@users.noreply.github.com> -Date: Fri, 24 May 2024 01:23:55 +0200 -Subject: [PATCH] 00438: Fix ThreadedVSOCKSocketStreamTest (GH-119465) - (GH-119479) (#119484) - -Fix ThreadedVSOCKSocketStreamTest: if get_cid() returns the host -address or the "any" address, use the local communication address -(loopback): VMADDR_CID_LOCAL. - -On Linux 6.9, apparently, the /dev/vsock device is now available but -get_cid() returns VMADDR_CID_ANY (-1). - -(cherry picked from commit c750061047ee520d8299334df4b112fd983d7e48) - -Co-authored-by: Victor Stinner -(cherry picked from commit e94dbe4ed83460f18bd72563c5f09f6cdc71f604) - -Co-authored-by: Victor Stinner ---- - Lib/test/test_socket.py | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py -index 0050298b41..12b90dcacb 100644 ---- a/Lib/test/test_socket.py -+++ b/Lib/test/test_socket.py -@@ -41,6 +41,7 @@ - # test unicode string and carriage return - MSG = 'Michael Gilfix was here\u1234\r\n'.encode('utf-8') - -+VMADDR_CID_LOCAL = 1 - VSOCKPORT = 1234 - AIX = platform.system() == "AIX" - -@@ -124,8 +125,8 @@ def _have_socket_qipcrtr(): - - def _have_socket_vsock(): - """Check whether AF_VSOCK sockets are supported on this host.""" -- ret = get_cid() is not None -- return ret -+ cid = get_cid() -+ return (cid is not None) - - - def _have_socket_bluetooth(): -@@ -487,8 +488,6 @@ def clientTearDown(self): - @unittest.skipIf(fcntl is None, "need fcntl") - @unittest.skipUnless(HAVE_SOCKET_VSOCK, - 'VSOCK sockets required for this test.') --@unittest.skipUnless(get_cid() != 2, -- "This test can only be run on a virtual guest.") - class ThreadedVSOCKSocketStreamTest(unittest.TestCase, ThreadableTest): - - def __init__(self, methodName='runTest'): -@@ -509,6 +508,9 @@ def clientSetUp(self): - self.cli = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM) - self.addCleanup(self.cli.close) - cid = get_cid() -+ if cid in (socket.VMADDR_CID_HOST, socket.VMADDR_CID_ANY): -+ # gh-119461: Use the local communication address (loopback) -+ cid = VMADDR_CID_LOCAL - self.cli.connect((cid, VSOCKPORT)) - - def testStream(self): diff --git a/00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch b/00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch deleted file mode 100644 index 5d005cb..0000000 --- a/00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Seth Michael Larson -Date: Fri, 31 Jan 2025 11:41:34 -0600 -Subject: [PATCH] 00450: CVE-2025-0938: Disallow square brackets ([ and ]) in - domain names for parsed URLs - -Co-authored-by: Peter Bierma ---- - Lib/test/test_urlparse.py | 37 ++++++++++++++++++- - Lib/urllib/parse.py | 20 +++++++++- - ...-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | 4 ++ - 3 files changed, 58 insertions(+), 3 deletions(-) - create mode 100644 Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst - -diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py -index f2ffc452e5..280644ef0b 100644 ---- a/Lib/test/test_urlparse.py -+++ b/Lib/test/test_urlparse.py -@@ -1149,16 +1149,51 @@ def test_invalid_bracketed_hosts(self): - self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query') - self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query') - self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]/') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix/') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]?') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix?') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]/') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix/') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]?') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix?') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a1') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a1') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:1a') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:1a') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:/') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:?') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@prefix.[v6a.ip]') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@[v6a.ip].suffix') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip]') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip[') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip].suffix') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip[suffix') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip') -+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[suffix') - - def test_splitting_bracketed_hosts(self): -- p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query') -+ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]:1234/path?query') - self.assertEqual(p1.hostname, 'v6a.ip') - self.assertEqual(p1.username, 'user') - self.assertEqual(p1.path, '/path') -+ self.assertEqual(p1.port, 1234) - p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query') - self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test') - self.assertEqual(p2.username, 'user') - self.assertEqual(p2.path, '/path') -+ self.assertIs(p2.port, None) - p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query') - self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test') - self.assertEqual(p3.username, 'user') -diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py -index 07e3248504..e1ee36d98e 100644 ---- a/Lib/urllib/parse.py -+++ b/Lib/urllib/parse.py -@@ -442,6 +442,23 @@ def _checknetloc(netloc): - raise ValueError("netloc '" + netloc + "' contains invalid " + - "characters under NFKC normalization") - -+def _check_bracketed_netloc(netloc): -+ # Note that this function must mirror the splitting -+ # done in NetlocResultMixins._hostinfo(). -+ hostname_and_port = netloc.rpartition('@')[2] -+ before_bracket, have_open_br, bracketed = hostname_and_port.partition('[') -+ if have_open_br: -+ # No data is allowed before a bracket. -+ if before_bracket: -+ raise ValueError("Invalid IPv6 URL") -+ hostname, _, port = bracketed.partition(']') -+ # No data is allowed after the bracket but before the port delimiter. -+ if port and not port.startswith(":"): -+ raise ValueError("Invalid IPv6 URL") -+ else: -+ hostname, _, port = hostname_and_port.partition(':') -+ _check_bracketed_host(hostname) -+ - # Valid bracketed hosts are defined in - # https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/ - def _check_bracketed_host(hostname): -@@ -505,8 +522,7 @@ def urlsplit(url, scheme='', allow_fragments=True): - (']' in netloc and '[' not in netloc)): - raise ValueError("Invalid IPv6 URL") - if '[' in netloc and ']' in netloc: -- bracketed_host = netloc.partition('[')[2].partition(']')[0] -- _check_bracketed_host(bracketed_host) -+ _check_bracketed_netloc(netloc) - if allow_fragments and '#' in url: - url, fragment = url.split('#', 1) - if '?' in url: -diff --git a/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst -new file mode 100644 -index 0000000000..bff1bc6b0d ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst -@@ -0,0 +1,4 @@ -+When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` host -+parsing would not reject domain names containing square brackets (``[`` and -+``]``). Square brackets are only valid for IPv6 and IPvFuture hosts according to -+`RFC 3986 Section 3.2.2 `__. diff --git a/python3.10.spec b/python3.10.spec index 221d3c6..d01fa94 100644 --- a/python3.10.spec +++ b/python3.10.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}.16 +%global general_version %{pybasever}.17 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 6%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -322,21 +322,6 @@ Patch251: 00251-change-user-install-location.patch # https://github.com/GrahamDumpleton/mod_wsgi/issues/730 Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch -# 00438 # 640f507108d102da99fa2f39d268a43f86c97acb -# Fix ThreadedVSOCKSocketStreamTest (GH-119465) (GH-119479) (#119484) -# -# Fix ThreadedVSOCKSocketStreamTest: if get_cid() returns the host -# address or the "any" address, use the local communication address -# (loopback): VMADDR_CID_LOCAL. -# -# On Linux 6.9, apparently, the /dev/vsock device is now available but -# get_cid() returns VMADDR_CID_ANY (-1). -Patch438: 00438-fix-threadedvsocksocketstreamtest-gh-119465-gh-119479-119484.patch - -# 00450 # 4ab8663661748eb994c09e4ae89f59eb84c5d3ea -# CVE-2025-0938: Disallow square brackets ([ and ]) in domain names for parsed URLs -Patch450: 00450-cve-2025-0938-disallow-square-brackets-and-in-domain-names-for-parsed-urls.patch - # 00452 # eb11d070c5af7d1b5e47f4e02186152d08eaf793 # Properly apply exported CFLAGS for dtrace/systemtap builds # @@ -1635,6 +1620,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Apr 09 2025 Miro Hrončok - 3.10.17-1 +- Update to 3.10.17 + * Mon Mar 31 2025 Charalampos Stratakis - 3.10.16-6 - Properly apply exported CFLAGS for dtrace/systemtap builds - Fixes: rhbz#2356303 diff --git a/sources b/sources index fe5766d..7d7438b 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.16.tar.xz) = a6b004974db93f21590f00b9b1a569dfd8c3e334f8c6a8eb8997dec5646fa4515cfc02a7dabea9e4f75f908938dc64333ce4899b9a26aff97f9ffcb027fa2bca -SHA512 (Python-3.10.16.tar.xz.asc) = 18032fdb60a022d6381b1137789ada1c4bb198049616ed158fb548e728dd1fb95d116a86c41c852ca2acc9127baf3cdd9644a1e2df90ae9c3ffcd66eabf454d6 +SHA512 (Python-3.10.17.tar.xz) = 11b1e647f8db05041bcafe110698af8bf5e9f7c8d23c0e9eb568a60544bb9a9e9c3ac94b34f0898f0d4e6c23da3cb81f844ae9d9c8b750058763502eaba39880 +SHA512 (Python-3.10.17.tar.xz.asc) = f5fea78e2ea413c9befb6181787b3a5ea3bc0f5dbf808a94465b558c09353482cd34631a4c505f72aa343a2f4fae291453324cd8e6b18df214baaf4680fc17cf From 234d41ca6b6c9e9e805bb0de22a1c7d902daa65b Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Wed, 16 Apr 2025 22:47:54 +0200 Subject: [PATCH 091/112] test_ssl: Don't stop ThreadedEchoServer on OSError in ConnectionHandler Fixes: rhbz#2355052 --- ...rver-on-oserror-in-connectionhandler.patch | 80 +++++++++++++++++++ python3.10.spec | 21 ++++- 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch diff --git a/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch b/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch new file mode 100644 index 0000000..7b83971 --- /dev/null +++ b/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Mon, 11 Nov 2024 15:26:10 +0100 +Subject: [PATCH] 00458: test_ssl: Don't stop ThreadedEchoServer on OSError in + ConnectionHandler + +If `read()` in the ConnectionHandler thread raises `OSError` (except `ConnectionError`), +the ConnectionHandler shuts down the entire ThreadedEchoServer, +preventing further connections. +It also does that for `EPROTOTYPE` in `wrap_conn`. + +Make sure that the context manager *is* used, and remove the `server.stop()` +calls from ConnectionHandler. + +Backported from 3.12+: +https://github.com/python/cpython/pull/126503 + +Co-authored-by: Petr Viktorin +--- + Lib/test/test_ssl.py | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index a1a581a907..0f1397de73 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -2488,7 +2488,6 @@ def wrap_conn(self): + # See also http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ + if e.errno != errno.EPROTOTYPE and sys.platform != "darwin": + self.running = False +- self.server.stop() + self.close() + return False + else: +@@ -2623,10 +2622,6 @@ def run(self): + self.close() + self.running = False + +- # normally, we'd just stop here, but for the test +- # harness, we want to stop the server +- self.server.stop() +- + def __init__(self, certificate=None, ssl_version=None, + certreqs=None, cacerts=None, + chatty=True, connectionchatty=False, starttls_server=False, +@@ -2660,21 +2655,33 @@ def __init__(self, certificate=None, ssl_version=None, + self.conn_errors = [] + threading.Thread.__init__(self) + self.daemon = True ++ self._in_context = False + + def __enter__(self): ++ if self._in_context: ++ raise ValueError('Re-entering ThreadedEchoServer context') ++ self._in_context = True + self.start(threading.Event()) + self.flag.wait() + return self + + def __exit__(self, *args): ++ assert self._in_context ++ self._in_context = False + self.stop() + self.join() + + def start(self, flag=None): ++ if not self._in_context: ++ raise ValueError( ++ 'ThreadedEchoServer must be used as a context manager') + self.flag = flag + threading.Thread.start(self) + + def run(self): ++ if not self._in_context: ++ raise ValueError( ++ 'ThreadedEchoServer must be used as a context manager') + self.sock.settimeout(1.0) + self.sock.listen(5) + self.active = True diff --git a/python3.10.spec b/python3.10.spec index d01fa94..0512cb9 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -334,6 +334,21 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # even when cross-compiling. Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch +# 00458 # ee47b2530c18d1e0b414f5a0738ddce28e7510f4 +# test_ssl: Don't stop ThreadedEchoServer on OSError in ConnectionHandler +# +# If `read()` in the ConnectionHandler thread raises `OSError` (except `ConnectionError`), +# the ConnectionHandler shuts down the entire ThreadedEchoServer, +# preventing further connections. +# It also does that for `EPROTOTYPE` in `wrap_conn`. +# +# Make sure that the context manager *is* used, and remove the `server.stop()` +# calls from ConnectionHandler. +# +# Backported from 3.12+: +# https://github.com/python/cpython/pull/126503 +Patch458: 00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1620,6 +1635,10 @@ CheckPython optimized # ====================================================== %changelog +* Wed Apr 16 2025 Charalampos Stratakis - 3.10.17-2 +- test_ssl: Don't stop ThreadedEchoServer on OSError in ConnectionHandler +- Fixes: rhbz#2355052 + * Wed Apr 09 2025 Miro Hrončok - 3.10.17-1 - Update to 3.10.17 From 772c5976f4261a78d3bd7af3ab4331adccf5f9fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Thu, 17 Apr 2025 11:43:22 +0200 Subject: [PATCH 092/112] Regenerate patches with updated importpatches script --- 00001-rpath.patch | 5 +++-- 00251-change-user-install-location.patch | 2 +- ...ing-_shutdown-for-the-main-thread-gh-28549-gh-28589.patch | 4 ++-- ...y-apply-exported-cflags-for-dtrace-systemtap-builds.patch | 3 +-- ...-threadedechoserver-on-oserror-in-connectionhandler.patch | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/00001-rpath.patch b/00001-rpath.patch index 778c077..58e0d8f 100644 --- a/00001-rpath.patch +++ b/00001-rpath.patch @@ -1,8 +1,9 @@ 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: =?UTF-8?q?00001:=20Fixup=20distutils/unixccompiler.py=20to=20remo?= + =?UTF-8?q?ve=20standard=20library=20path=20from=20rpath=0AWas=20Patch0=20?= + =?UTF-8?q?in=20ivazquez'=20python3000=20specfile?= --- Lib/distutils/unixccompiler.py | 9 +++++++++ diff --git a/00251-change-user-install-location.patch b/00251-change-user-install-location.patch index b0a4c9c..7b68621 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: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 15 Feb 2021 12:19:27 +0100 -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/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 7ab6c6c..7dbd3bb 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: Tue, 7 Dec 2021 14:41:59 +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 38c67738c64304928c68d5c2bd78bbb01d979b94. It introduced regression causing FreeIPA's tests to fail. diff --git a/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch b/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch index 359d9ac..2e2f3c6 100644 --- a/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch +++ b/00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch @@ -2,8 +2,7 @@ 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: [PATCH] 00452: Properly apply exported CFLAGS for dtrace/systemtap - builds +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 diff --git a/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch b/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch index 7b83971..ab62987 100644 --- a/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch +++ b/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch @@ -2,7 +2,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "Miss Islington (bot)" <31488909+miss-islington@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:26:10 +0100 -Subject: [PATCH] 00458: test_ssl: Don't stop ThreadedEchoServer on OSError in +Subject: 00458: test_ssl: Don't stop ThreadedEchoServer on OSError in ConnectionHandler If `read()` in the ConnectionHandler thread raises `OSError` (except `ConnectionError`), From 75538d3684a89581b6b85a5336f0cd6a4f19619e Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Tue, 13 May 2025 02:32:52 +0200 Subject: [PATCH 093/112] Fix PySSL_SetError handling SSL_ERROR_SYSCALL This fixes random flakiness of test_ssl on stressed machines --- 00001-rpath.patch | 5 +- ..._seterror-handling-ssl_error_syscall.patch | 214 ++++++++++++++++++ python3.10.spec | 22 +- 3 files changed, 235 insertions(+), 6 deletions(-) create mode 100644 00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch diff --git a/00001-rpath.patch b/00001-rpath.patch index 58e0d8f..9498516 100644 --- a/00001-rpath.patch +++ b/00001-rpath.patch @@ -1,9 +1,8 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 13 Jan 2010 21:25:18 +0000 -Subject: =?UTF-8?q?00001:=20Fixup=20distutils/unixccompiler.py=20to=20remo?= - =?UTF-8?q?ve=20standard=20library=20path=20from=20rpath=0AWas=20Patch0=20?= - =?UTF-8?q?in=20ivazquez'=20python3000=20specfile?= +Subject: 00001: Fixup distutils/unixccompiler.py to remove standard library + path from rpath Was Patch0 in ivazquez' python3000 specfile --- Lib/distutils/unixccompiler.py | 9 +++++++++ diff --git a/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch b/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch new file mode 100644 index 0000000..5c0cda1 --- /dev/null +++ b/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch @@ -0,0 +1,214 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: yevgeny hong +Date: Tue, 26 Mar 2024 16:45:43 +0900 +Subject: 00462: Fix PySSL_SetError handling SSL_ERROR_SYSCALL + +Python 3.10 changed from using SSL_write() and SSL_read() to SSL_write_ex() and +SSL_read_ex(), but did not update handling of the return value. + +Change error handling so that the return value is not examined. +OSError (not EOF) is now returned when retval is 0. + +This resolves the issue of failing tests when a system is +stressed on OpenSSL 3.5. + +Co-authored-by: Serhiy Storchaka +Co-authored-by: Petr Viktorin +--- + Lib/test/test_ssl.py | 41 +++++++--------- + ...-02-18-09-50-31.gh-issue-115627.HGchj0.rst | 2 + + Modules/_ssl.c | 48 +++++++------------ + 3 files changed, 38 insertions(+), 53 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2024-02-18-09-50-31.gh-issue-115627.HGchj0.rst + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 0f1397de73..21d3676c22 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -2605,16 +2605,18 @@ def run(self): + self.write(msg.lower()) + except OSError as e: + # handles SSLError and socket errors ++ if isinstance(e, ConnectionError): ++ # OpenSSL 1.1.1 sometimes raises ++ # ConnectionResetError when connection is not ++ # shut down gracefully. ++ if self.server.chatty and support.verbose: ++ print(f" Connection reset by peer: {self.addr}") ++ ++ self.close() ++ self.running = False ++ return + if self.server.chatty and support.verbose: +- if isinstance(e, ConnectionError): +- # OpenSSL 1.1.1 sometimes raises +- # ConnectionResetError when connection is not +- # shut down gracefully. +- print( +- f" Connection reset by peer: {self.addr}" +- ) +- else: +- handle_error("Test server failure:\n") ++ handle_error("Test server failure:\n") + try: + self.write(b"ERROR\n") + except OSError: +@@ -3296,23 +3298,16 @@ def test_wrong_cert_tls13(self): + client_context.wrap_socket(socket.socket(), + server_hostname=hostname, + suppress_ragged_eofs=False) as s: +- # TLS 1.3 perform client cert exchange after handshake + s.connect((HOST, server.port)) +- try: ++ with self.assertRaisesRegex( ++ OSError, ++ 'alert unknown ca|EOF occurred|TLSV1_ALERT_UNKNOWN_CA|closed by the remote host|Connection reset by peer' ++ ): ++ # TLS 1.3 perform client cert exchange after handshake + s.write(b'data') + s.read(1000) + s.write(b'should have failed already') + s.read(1000) +- except ssl.SSLError as e: +- if support.verbose: +- sys.stdout.write("\nSSLError is %r\n" % e) +- except OSError as e: +- if e.errno != errno.ECONNRESET: +- raise +- if support.verbose: +- sys.stdout.write("\nsocket.error is %r\n" % e) +- else: +- self.fail("Use of invalid cert should have failed!") + + def test_rude_shutdown(self): + """A brutal shutdown of an SSL server should raise an OSError +@@ -4558,8 +4553,8 @@ def msg_cb(conn, direction, version, content_type, msg_type, data): + # test sometimes fails with EOF error. Test passes as long as + # server aborts connection with an error. + with self.assertRaisesRegex( +- ssl.SSLError, +- '(certificate required|EOF occurred)' ++ OSError, ++ 'certificate required|EOF occurred|closed by the remote host|Connection reset by peer' + ): + # receive CertificateRequest + data = s.recv(1024) +diff --git a/Misc/NEWS.d/next/Library/2024-02-18-09-50-31.gh-issue-115627.HGchj0.rst b/Misc/NEWS.d/next/Library/2024-02-18-09-50-31.gh-issue-115627.HGchj0.rst +new file mode 100644 +index 0000000000..75d926ab59 +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2024-02-18-09-50-31.gh-issue-115627.HGchj0.rst +@@ -0,0 +1,2 @@ ++Fix the :mod:`ssl` module error handling of connection terminate by peer. ++It now throws an OSError with the appropriate error code instead of an EOFError. +diff --git a/Modules/_ssl.c b/Modules/_ssl.c +index 6852cc363b..91bf27bfef 100644 +--- a/Modules/_ssl.c ++++ b/Modules/_ssl.c +@@ -582,7 +582,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) { + } + + static PyObject * +-PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) ++PySSL_SetError(PySSLSocket *sslsock, const char *filename, int lineno) + { + PyObject *type; + char *errstr = NULL; +@@ -595,7 +595,6 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) + _sslmodulestate *state = get_state_sock(sslsock); + type = state->PySSLErrorObject; + +- assert(ret <= 0); + e = ERR_peek_last_error(); + + if (sslsock->ssl != NULL) { +@@ -628,32 +627,21 @@ PySSL_SetError(PySSLSocket *sslsock, int ret, const char *filename, int lineno) + case SSL_ERROR_SYSCALL: + { + if (e == 0) { +- PySocketSockObject *s = GET_SOCKET(sslsock); +- if (ret == 0 || (((PyObject *)s) == Py_None)) { ++ /* underlying BIO reported an I/O error */ ++ ERR_clear_error(); ++#ifdef MS_WINDOWS ++ if (err.ws) { ++ return PyErr_SetFromWindowsErr(err.ws); ++ } ++#endif ++ if (err.c) { ++ errno = err.c; ++ return PyErr_SetFromErrno(PyExc_OSError); ++ } ++ else { + p = PY_SSL_ERROR_EOF; + type = state->PySSLEOFErrorObject; + errstr = "EOF occurred in violation of protocol"; +- } else if (s && ret == -1) { +- /* underlying BIO reported an I/O error */ +- ERR_clear_error(); +-#ifdef MS_WINDOWS +- if (err.ws) { +- return PyErr_SetFromWindowsErr(err.ws); +- } +-#endif +- if (err.c) { +- errno = err.c; +- return PyErr_SetFromErrno(PyExc_OSError); +- } +- else { +- p = PY_SSL_ERROR_EOF; +- type = state->PySSLEOFErrorObject; +- errstr = "EOF occurred in violation of protocol"; +- } +- } else { /* possible? */ +- p = PY_SSL_ERROR_SYSCALL; +- type = state->PySSLSyscallErrorObject; +- errstr = "Some I/O error occurred"; + } + } else { + if (ERR_GET_LIB(e) == ERR_LIB_SYS) { +@@ -1014,7 +1002,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) + err.ssl == SSL_ERROR_WANT_WRITE); + Py_XDECREF(sock); + if (ret < 1) +- return PySSL_SetError(self, ret, __FILE__, __LINE__); ++ return PySSL_SetError(self, __FILE__, __LINE__); + if (PySSL_ChainExceptions(self) < 0) + return NULL; + Py_RETURN_NONE; +@@ -2433,7 +2421,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) + + Py_XDECREF(sock); + if (retval == 0) +- return PySSL_SetError(self, retval, __FILE__, __LINE__); ++ return PySSL_SetError(self, __FILE__, __LINE__); + if (PySSL_ChainExceptions(self) < 0) + return NULL; + return PyLong_FromSize_t(count); +@@ -2463,7 +2451,7 @@ _ssl__SSLSocket_pending_impl(PySSLSocket *self) + self->err = err; + + if (count < 0) +- return PySSL_SetError(self, count, __FILE__, __LINE__); ++ return PySSL_SetError(self, __FILE__, __LINE__); + else + return PyLong_FromLong(count); + } +@@ -2585,7 +2573,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, Py_ssize_t len, + err.ssl == SSL_ERROR_WANT_WRITE); + + if (retval == 0) { +- PySSL_SetError(self, retval, __FILE__, __LINE__); ++ PySSL_SetError(self, __FILE__, __LINE__); + goto error; + } + if (self->exc_type != NULL) +@@ -2709,7 +2697,7 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) + } + if (ret < 0) { + Py_XDECREF(sock); +- PySSL_SetError(self, ret, __FILE__, __LINE__); ++ PySSL_SetError(self, __FILE__, __LINE__); + return NULL; + } + if (self->exc_type != NULL) diff --git a/python3.10.spec b/python3.10.spec index 0512cb9..b91f16c 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -286,8 +286,7 @@ Source11: idle3.appdata.xml # (Patches taken from github.com/fedora-python/cpython) # 00001 # d06a8853cf4bae9e115f45e1d531d2dc152c5cc8 -# Fixup distutils/unixccompiler.py to remove standard library path from rpath -# Was Patch0 in ivazquez' python3000 specfile +# Fixup distutils/unixccompiler.py to remove standard library path from rpath Was Patch0 in ivazquez' python3000 specfile Patch1: 00001-rpath.patch # 00251 # 8448a0d6edd44d0818b8c02dc603b769b5363e5b @@ -349,6 +348,19 @@ Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch # https://github.com/python/cpython/pull/126503 Patch458: 00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch +# 00462 # f0db87ee65704fa5545ea25f2cca8c43fc639fab +# Fix PySSL_SetError handling SSL_ERROR_SYSCALL +# +# Python 3.10 changed from using SSL_write() and SSL_read() to SSL_write_ex() and +# SSL_read_ex(), but did not update handling of the return value. +# +# Change error handling so that the return value is not examined. +# OSError (not EOF) is now returned when retval is 0. +# +# This resolves the issue of failing tests when a system is +# stressed on OpenSSL 3.5. +Patch462: 00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1635,6 +1647,10 @@ CheckPython optimized # ====================================================== %changelog +* Tue May 13 2025 Charalampos Stratakis - 3.10.17-3 +- Fix PySSL_SetError handling SSL_ERROR_SYSCALL +- This fixes random flakiness of test_ssl on stressed machines + * Wed Apr 16 2025 Charalampos Stratakis - 3.10.17-2 - test_ssl: Don't stop ThreadedEchoServer on OSError in ConnectionHandler - Fixes: rhbz#2355052 From 6c238008d198b1eba6f88c3fcec17d99b94e1f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Wed, 4 Jun 2025 09:39:00 +0200 Subject: [PATCH 094/112] Update to 3.10.18 --- ...rver-on-oserror-in-connectionhandler.patch | 80 ------------------- python3.10.spec | 22 ++--- sources | 4 +- 3 files changed, 7 insertions(+), 99 deletions(-) delete mode 100644 00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch diff --git a/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch b/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch deleted file mode 100644 index ab62987..0000000 --- a/00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: "Miss Islington (bot)" - <31488909+miss-islington@users.noreply.github.com> -Date: Mon, 11 Nov 2024 15:26:10 +0100 -Subject: 00458: test_ssl: Don't stop ThreadedEchoServer on OSError in - ConnectionHandler - -If `read()` in the ConnectionHandler thread raises `OSError` (except `ConnectionError`), -the ConnectionHandler shuts down the entire ThreadedEchoServer, -preventing further connections. -It also does that for `EPROTOTYPE` in `wrap_conn`. - -Make sure that the context manager *is* used, and remove the `server.stop()` -calls from ConnectionHandler. - -Backported from 3.12+: -https://github.com/python/cpython/pull/126503 - -Co-authored-by: Petr Viktorin ---- - Lib/test/test_ssl.py | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py -index a1a581a907..0f1397de73 100644 ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -2488,7 +2488,6 @@ def wrap_conn(self): - # See also http://erickt.github.io/blog/2014/11/19/adventures-in-debugging-a-potential-osx-kernel-bug/ - if e.errno != errno.EPROTOTYPE and sys.platform != "darwin": - self.running = False -- self.server.stop() - self.close() - return False - else: -@@ -2623,10 +2622,6 @@ def run(self): - self.close() - self.running = False - -- # normally, we'd just stop here, but for the test -- # harness, we want to stop the server -- self.server.stop() -- - def __init__(self, certificate=None, ssl_version=None, - certreqs=None, cacerts=None, - chatty=True, connectionchatty=False, starttls_server=False, -@@ -2660,21 +2655,33 @@ def __init__(self, certificate=None, ssl_version=None, - self.conn_errors = [] - threading.Thread.__init__(self) - self.daemon = True -+ self._in_context = False - - def __enter__(self): -+ if self._in_context: -+ raise ValueError('Re-entering ThreadedEchoServer context') -+ self._in_context = True - self.start(threading.Event()) - self.flag.wait() - return self - - def __exit__(self, *args): -+ assert self._in_context -+ self._in_context = False - self.stop() - self.join() - - def start(self, flag=None): -+ if not self._in_context: -+ raise ValueError( -+ 'ThreadedEchoServer must be used as a context manager') - self.flag = flag - threading.Thread.start(self) - - def run(self): -+ if not self._in_context: -+ raise ValueError( -+ 'ThreadedEchoServer must be used as a context manager') - self.sock.settimeout(1.0) - self.sock.listen(5) - self.active = True diff --git a/python3.10.spec b/python3.10.spec index b91f16c..b722825 100644 --- a/python3.10.spec +++ b/python3.10.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}.17 +%global general_version %{pybasever}.18 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -333,21 +333,6 @@ Patch371: 00371-revert-bpo-1596321-fix-threading-_shutdown-for-the-main-thread-g # even when cross-compiling. Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch -# 00458 # ee47b2530c18d1e0b414f5a0738ddce28e7510f4 -# test_ssl: Don't stop ThreadedEchoServer on OSError in ConnectionHandler -# -# If `read()` in the ConnectionHandler thread raises `OSError` (except `ConnectionError`), -# the ConnectionHandler shuts down the entire ThreadedEchoServer, -# preventing further connections. -# It also does that for `EPROTOTYPE` in `wrap_conn`. -# -# Make sure that the context manager *is* used, and remove the `server.stop()` -# calls from ConnectionHandler. -# -# Backported from 3.12+: -# https://github.com/python/cpython/pull/126503 -Patch458: 00458-test_ssl-don-t-stop-threadedechoserver-on-oserror-in-connectionhandler.patch - # 00462 # f0db87ee65704fa5545ea25f2cca8c43fc639fab # Fix PySSL_SetError handling SSL_ERROR_SYSCALL # @@ -1647,6 +1632,9 @@ CheckPython optimized # ====================================================== %changelog +* Wed Jun 04 2025 Tomáš Hrnčiar - 3.10.18-1 +- Update to 3.10.18 + * Tue May 13 2025 Charalampos Stratakis - 3.10.17-3 - Fix PySSL_SetError handling SSL_ERROR_SYSCALL - This fixes random flakiness of test_ssl on stressed machines diff --git a/sources b/sources index 7d7438b..64bd7d3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.17.tar.xz) = 11b1e647f8db05041bcafe110698af8bf5e9f7c8d23c0e9eb568a60544bb9a9e9c3ac94b34f0898f0d4e6c23da3cb81f844ae9d9c8b750058763502eaba39880 -SHA512 (Python-3.10.17.tar.xz.asc) = f5fea78e2ea413c9befb6181787b3a5ea3bc0f5dbf808a94465b558c09353482cd34631a4c505f72aa343a2f4fae291453324cd8e6b18df214baaf4680fc17cf +SHA512 (Python-3.10.18.tar.xz) = 2c444f024cd15babd156964b50aa0245020a17c0c600250ffcf112e91594a3d6e1fb87c9b87a57cb7a802dae90004d801ed95a3103d79aefb8ed714279997708 +SHA512 (Python-3.10.18.tar.xz.asc) = dbe1426b1b8371bf390b53595d2c656fbd311fed55ad3c705e175fa0c72d51a022f286877ec55ad74547a3b57ae945c9af7ece4dacc7132e21b9b7eb4421add6 From ec3cbfebe9b9284a1b03109477aa73457b07447d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 26 Jun 2025 13:13:07 +0200 Subject: [PATCH 095/112] Fixup the patch 1 commit message after the importpatches/exportpatches change This fixes up 772c5976f4261a78d3bd7af3ab4331adccf5f9fe + 75538d3684a89581b6b85a5336f0cd6a4f19619e. --- 00001-rpath.patch | 3 ++- python3.10.spec | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/00001-rpath.patch b/00001-rpath.patch index 9498516..cd063e5 100644 --- a/00001-rpath.patch +++ b/00001-rpath.patch @@ -2,8 +2,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 Was Patch0 in ivazquez' python3000 specfile + path from rpath +Was Patch0 in ivazquez' python3000 specfile --- Lib/distutils/unixccompiler.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index b722825..64ead49 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -286,7 +286,9 @@ Source11: idle3.appdata.xml # (Patches taken from github.com/fedora-python/cpython) # 00001 # d06a8853cf4bae9e115f45e1d531d2dc152c5cc8 -# Fixup distutils/unixccompiler.py to remove standard library path from rpath Was Patch0 in ivazquez' python3000 specfile +# Fixup distutils/unixccompiler.py to remove standard library path from rpath +# +# Was Patch0 in ivazquez' python3000 specfile Patch1: 00001-rpath.patch # 00251 # 8448a0d6edd44d0818b8c02dc603b769b5363e5b From 9d6cf58680bd1e6b1724e619140915f784e59437 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 25 Jul 2025 11:18:56 +0000 Subject: [PATCH 096/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 64ead49..9e6fd43 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -1634,6 +1634,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Jul 25 2025 Fedora Release Engineering - 3.10.18-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + * Wed Jun 04 2025 Tomáš Hrnčiar - 3.10.18-1 - Update to 3.10.18 From 207259522d0b3054a2128fad5695067bda8bd0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Zachar?= Date: Fri, 25 Jul 2025 13:33:03 +0200 Subject: [PATCH 097/112] Drop STI and use tmt instead Resolves: rhbz#2383056 --- {tests/.fmf => .fmf}/version | 0 plan.fmf | 61 ++++++++++++++++++++++++++++++++++++ tests/provision.fmf | 4 --- tests/tests.yml | 55 -------------------------------- 4 files changed, 61 insertions(+), 59 deletions(-) rename {tests/.fmf => .fmf}/version (100%) create mode 100644 plan.fmf delete mode 100644 tests/provision.fmf delete mode 100644 tests/tests.yml diff --git a/tests/.fmf/version b/.fmf/version similarity index 100% rename from tests/.fmf/version rename to .fmf/version diff --git a/plan.fmf b/plan.fmf new file mode 100644 index 0000000..71f3e63 --- /dev/null +++ b/plan.fmf @@ -0,0 +1,61 @@ +execute: + how: tmt + +provision: + hardware: + memory: '>= 3 GB' + +environment: + pybasever: '3.10' + +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: smoke_virtualenv + path: /smoke + test: "VERSION=${pybasever} METHOD=virtualenv ./venv.sh" + - name: debugsmoke + path: /smoke + test: "PYTHON=python${pybasever}d TOX=false VERSION=${pybasever} ./venv.sh" + - name: selftest + path: /selftest + test: "VERSION=${pybasever} X='' ./parallel.sh" + - name: debugtest + path: /selftest + test: "VERSION=${pybasever} PYTHON=python${pybasever}d X='' ./parallel.sh" + - name: debugflags + path: /flags + test: "python${pybasever}d ./assertflags.py -O0" + - 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}-debug" # for leak testing + - "python${pybasever}-devel" # for extension building in venv and selftest + - "python${pybasever}-tkinter" # for selftest + - "python${pybasever}-test" # for selftest + - tox # for venv tests + - virtualenv # for virtualenv tests + - glibc-all-langpacks # for locale tests + - marshalparser # for testing compatibility (magic numbers) with marshalparser + - rpm # for debugging + - 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/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 460b4a1..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,55 +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" - pybasever: "3.10" - tests: - - rpm_qa: - run: rpm -qa - - smoke: - dir: python/smoke - run: "VERSION={{ pybasever }} ./venv.sh" - - smoke_virtualenv: - dir: python/smoke - run: "VERSION={{ pybasever }} METHOD=virtualenv ./venv.sh" - - debugsmoke: - dir: python/smoke - run: "PYTHON=python{{ pybasever }}d TOX=false VERSION={{ pybasever }} ./venv.sh" - - selftest: - dir: python/selftest - run: "VERSION={{ pybasever }} X='' ./parallel.sh" - - debugtest: - dir: python/selftest - run: "VERSION={{ pybasever }} PYTHON=python{{ pybasever }}d X='' ./parallel.sh" - - debugflags: - dir: python/flags - run: "python{{ pybasever }}d ./assertflags.py -O0" - - marshalparser: - dir: python/marshalparser - run: "VERSION={{ pybasever }} SAMPLE=10 test_marshalparser_compatibility.sh" - required_packages: - - gcc # for extension building in venv and selftest - - gdb # for test_gdb - - "python{{ pybasever }}" # the test subject - - "python{{ pybasever }}-debug" # for leak testing - - "python{{ pybasever }}-devel" # for extension building in venv and selftest - - "python{{ pybasever }}-tkinter" # for selftest - - "python{{ pybasever }}-test" # for selftest - - tox # for venv tests - - virtualenv # for virtualenv tests - - glibc-all-langpacks # for locale tests - - marshalparser # for testing compatibility (magic numbers) with marshalparser - - rpm # for debugging From b1fc74dd76704c00bde4673ae6520484d77e1dca Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 26 Aug 2025 10:01:22 +0200 Subject: [PATCH 098/112] rpminspect: Wrap strings with globs with single quotes It seems to be required since rpminspect 2.0: https://github.com/rpminspect/rpminspect/commit/1593c38ce46980e0279150706d1f7c7bdd82de28 --- rpminspect.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpminspect.yaml b/rpminspect.yaml index 83dfb5e..8cc18cb 100644 --- a/rpminspect.yaml +++ b/rpminspect.yaml @@ -1,22 +1,22 @@ # exclude test XML data (not always valid) from XML validity check: xml: ignore: - - /usr/lib*/python*/test/xmltestdata/* - - /usr/lib*/python*/test/xmltestdata/*/* + - '/usr/lib*/python*/test/xmltestdata/*' + - '/usr/lib*/python*/test/xmltestdata/*/*' # exclude _socket from ipv4 only functions check, it has both ipv4 and ipv6 only badfuncs: allowed: - /usr/lib*/python*/lib-dynload/_socket.*: + '/usr/lib*/python*/lib-dynload/_socket.*': - inet_aton - inet_ntoa # exclude the debug build from annocheck entirely annocheck: ignore: - - /usr/bin/python*d - - /usr/lib*/libpython*d.so.1.0 - - /usr/lib*/python*/lib-dynload/*.cpython-*d-*-*-*.so + - '/usr/bin/python*d' + - '/usr/lib*/libpython*d.so.1.0' + - '/usr/lib*/python*/lib-dynload/*.cpython-*d-*-*-*.so' # don't report changed content of compiled files # that is expected with every toolchain update and not reproducible yet From a3bdce551cae631446ca1d887cf1c58cbaf31b45 Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Fri, 10 Oct 2025 14:22:08 +0200 Subject: [PATCH 099/112] Update to Python 3.10.19 --- python3.10.spec | 9 ++++++--- sources | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 9e6fd43..ed7b1b6 100644 --- a/python3.10.spec +++ b/python3.10.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}.18 +%global general_version %{pybasever}.19 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -68,7 +68,7 @@ License: Python-2.0.1 # from Python with the versions below. # This needs to be manually updated when we update Python. %global pip_version 23.0.1 -%global setuptools_version 65.5.0 +%global setuptools_version 79.0.1 # Expensive optimizations (mainly, profile-guided optimizations) %bcond_without optimizations @@ -1634,6 +1634,9 @@ CheckPython optimized # ====================================================== %changelog +* Fri Oct 10 2025 Karolina Surma - 3.10.19-1 +- Update to Python 3.10.19 + * Fri Jul 25 2025 Fedora Release Engineering - 3.10.18-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild diff --git a/sources b/sources index 64bd7d3..6de6cda 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.18.tar.xz) = 2c444f024cd15babd156964b50aa0245020a17c0c600250ffcf112e91594a3d6e1fb87c9b87a57cb7a802dae90004d801ed95a3103d79aefb8ed714279997708 -SHA512 (Python-3.10.18.tar.xz.asc) = dbe1426b1b8371bf390b53595d2c656fbd311fed55ad3c705e175fa0c72d51a022f286877ec55ad74547a3b57ae945c9af7ece4dacc7132e21b9b7eb4421add6 +SHA512 (Python-3.10.19.tar.xz) = 9ea1e952bb5f7c9cc8d3efd8e7ae0059c129b6e09d12ded7d4e22476fad35f2c8186b1e003ea35a0099ffa5ff0a114985c3e960fba84e7037670b840a3e19c68 +SHA512 (Python-3.10.19.tar.xz.asc) = 64bcee68c2f4e0718daaf19d405f4a5bd0ce3fc3d13bb5cbae8d4a36e419dd104c94323b497f1d06110f6b62a1b3b351279c534145f4e8cea9af0d7bb0a8b5c9 From bd23e23416c9d72129581321bfdc90b279c93f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 5 Sep 2025 11:41:55 +0000 Subject: [PATCH 100/112] Inject SBOM into the installed wheels (when using the bundled ones) --- python3.10.spec | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index ed7b1b6..2c5aee0 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -246,6 +246,9 @@ BuildRequires: /usr/sbin/ifconfig %if %{with rpmwheels} BuildRequires: %{python_wheel_pkg_prefix}-setuptools-wheel BuildRequires: %{python_wheel_pkg_prefix}-pip-wheel +%else +# For %%python_wheel_inject_sbom +BuildRequires: python-rpm-macros %endif %if %{without bootstrap} @@ -1064,6 +1067,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 # ====================================================== From 14cfcd8b1f83f11d889d8531d462f43a987d5f50 Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Tue, 6 Jan 2026 17:53:12 +0100 Subject: [PATCH 101/112] Require at least the same expat version as used during the build The versioned requirement is no longer valid - this happens again now with expat 2.7.2 introducing new symbols. Make the versioned requirement future-proof - the generated version will always match at least the one present in the buildroot during the Python build. --- python3.10.spec | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index 2c5aee0..6a4fa7e 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -192,8 +192,7 @@ BuildRequires: bluez-libs-devel BuildRequires: bzip2 BuildRequires: bzip2-devel BuildRequires: desktop-file-utils -# See the runtime requirement in the -libs subpackage -BuildRequires: expat-devel >= 2.6 +BuildRequires: expat-devel BuildRequires: findutils BuildRequires: gcc-c++ @@ -497,12 +496,20 @@ Recommends: (%{pkgname}-tkinter%{?_isa} = %{version}-%{release} if tk%{?_isa}) Requires: tzdata # The requirement on libexpat is generated, but we need to version it. -# When built with expat >= 2.6, but installed with older expat, we get: +# When built with a specific expat version, but installed with an older one, +# we sometimes get: # ImportError: /usr/lib64/python3.X/lib-dynload/pyexpat.cpython-....so: -# undefined symbol: XML_SetReparseDeferralEnabled +# undefined symbol: XML_... +# The pyexpat module has build-time checks for expat version to only use the +# available symbols. However, there is no runtime protection, so when the module +# is later installed with an older expat, it may error due to undefined symbols. # This breaks many things, including python -m venv. +# We avoid this problem by requiring at least the same version of expat that +# was used during the build time. # Other subpackages (like -debug) also need this, but they all depend on -libs. -Requires: expat >= 2.6 +%global expat_version %(LANG=C rpm -q --qf '%%{version}' expat.%{_target_cpu} | sed 's/.*not installed/0/') +Requires: expat >= %{expat_version} + # Since patch 251 changed from distutils to sysconfig, pip needed to be adapted # The previous versions could cause serious bugs during `sudo pip install --upgrade ...` @@ -1642,6 +1649,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Jan 06 2026 Karolina Surma - 3.10.19-2 +- Require at least the same expat version as used during the build time + * Fri Oct 10 2025 Karolina Surma - 3.10.19-1 - Update to Python 3.10.19 From 311900d817ce3e8b6439334b7140e827753ca833 Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Mon, 12 Jan 2026 11:55:39 +0100 Subject: [PATCH 102/112] Extend the expat requirement to differentiate between 32 and 64 arches (cherry picked from python3.15 commit a5ca170d3f1e6e19f5df66f21482c2b10593af42) --- python3.10.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 6a4fa7e..2691ab5 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -508,7 +508,7 @@ Requires: tzdata # was used during the build time. # Other subpackages (like -debug) also need this, but they all depend on -libs. %global expat_version %(LANG=C rpm -q --qf '%%{version}' expat.%{_target_cpu} | sed 's/.*not installed/0/') -Requires: expat >= %{expat_version} +Requires: expat%{?_isa} >= %{expat_version} # Since patch 251 changed from distutils to sysconfig, pip needed to be adapted From 6c0fab4bc9126543051bdacd26cd75d3d8918b2d Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sat, 17 Jan 2026 10:39:54 +0000 Subject: [PATCH 103/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 2691ab5..de79e10 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -1649,6 +1649,9 @@ CheckPython optimized # ====================================================== %changelog +* Sat Jan 17 2026 Fedora Release Engineering - 3.10.19-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild + * Tue Jan 06 2026 Karolina Surma - 3.10.19-2 - Require at least the same expat version as used during the build time From e0dac6a2c5af911856a043bb5280c77a2494b3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Mon, 9 Feb 2026 10:38:43 +0100 Subject: [PATCH 104/112] Security fixes for CVE-2026-0865, CVE-2025-15366 and CVE-2025-15367 --- 00473-cve-2026-0865.patch | 90 ++++++++++++++++++++++++++++++++++++++ 00474-cve-2025-15366.patch | 61 ++++++++++++++++++++++++++ 00475-cve-2025-15367.patch | 61 ++++++++++++++++++++++++++ python3.10.spec | 30 ++++++++++++- 4 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 00473-cve-2026-0865.patch create mode 100644 00474-cve-2025-15366.patch create mode 100644 00475-cve-2025-15367.patch diff --git a/00473-cve-2026-0865.patch b/00473-cve-2026-0865.patch new file mode 100644 index 0000000..3504e6b --- /dev/null +++ b/00473-cve-2026-0865.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Sat, 17 Jan 2026 11:46:21 -0600 +Subject: 00473: CVE-2026-0865 + + gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) + +* Add 'test.support' fixture for C0 control characters +* gh-143916: Reject control characters in wsgiref.headers.Headers +--- + Lib/test/support/__init__.py | 7 +++++++ + Lib/test/test_wsgiref.py | 12 +++++++++++- + Lib/wsgiref/headers.py | 3 +++ + .../2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst | 2 ++ + 4 files changed, 23 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst + +diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py +index 0d3b9634f1..d0492fe191 100644 +--- a/Lib/test/support/__init__.py ++++ b/Lib/test/support/__init__.py +@@ -2157,3 +2157,10 @@ def adjust_int_max_str_digits(max_digits): + yield + finally: + sys.set_int_max_str_digits(current) ++ ++ ++def control_characters_c0() -> list[str]: ++ """Returns a list of C0 control characters as strings. ++ C0 control characters defined as the byte range 0x00-0x1F, and 0x7F. ++ """ ++ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"] +diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py +index 42094f4677..01ca51ba45 100644 +--- a/Lib/test/test_wsgiref.py ++++ b/Lib/test/test_wsgiref.py +@@ -1,6 +1,6 @@ + from unittest import mock + from test import support +-from test.support import socket_helper ++from test.support import socket_helper, control_characters_c0 + from test.support import warnings_helper + from test.test_httpservers import NoLogRequestHandler + from unittest import TestCase +@@ -527,6 +527,16 @@ def testExtras(self): + '\r\n' + ) + ++ def testRaisesControlCharacters(self): ++ headers = Headers() ++ for c0 in control_characters_c0(): ++ self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val") ++ self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}") ++ self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param") ++ self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param") ++ self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}") ++ ++ + class ErrorHandler(BaseCGIHandler): + """Simple handler subclass for testing BaseHandler""" + +diff --git a/Lib/wsgiref/headers.py b/Lib/wsgiref/headers.py +index fab851c5a4..fd98e85d75 100644 +--- a/Lib/wsgiref/headers.py ++++ b/Lib/wsgiref/headers.py +@@ -9,6 +9,7 @@ + # existence of which force quoting of the parameter value. + import re + tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') ++_control_chars_re = re.compile(r'[\x00-\x1F\x7F]') + + def _formatparam(param, value=None, quote=1): + """Convenience function to format and return a key=value pair. +@@ -41,6 +42,8 @@ def __init__(self, headers=None): + def _convert_string_type(self, value): + """Convert/check value type.""" + if type(value) is str: ++ if _control_chars_re.search(value): ++ raise ValueError("Control characters not allowed in headers") + return value + raise AssertionError("Header names/values must be" + " of type str (got {0})".format(repr(value))) +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst +new file mode 100644 +index 0000000000..44bd0b2705 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst +@@ -0,0 +1,2 @@ ++Reject C0 control characters within wsgiref.headers.Headers fields, values, ++and parameters. diff --git a/00474-cve-2025-15366.patch b/00474-cve-2025-15366.patch new file mode 100644 index 0000000..0b4fd18 --- /dev/null +++ b/00474-cve-2025-15366.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Tue, 20 Jan 2026 14:45:42 -0600 +Subject: 00474: CVE-2025-15366 + +gh-143921: Reject control characters in IMAP commands + +(cherry-picked from commit 6262704b134db2a4ba12e85ecfbd968534f28b45) +--- + Lib/imaplib.py | 4 +++- + Lib/test/test_imaplib.py | 6 ++++++ + .../Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst | 1 + + 3 files changed, 10 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst + +diff --git a/Lib/imaplib.py b/Lib/imaplib.py +index 54122f985b..9ab8e43bbf 100644 +--- a/Lib/imaplib.py ++++ b/Lib/imaplib.py +@@ -132,7 +132,7 @@ + # We compile these in _mode_xxx. + _Literal = br'.*{(?P\d+)}$' + _Untagged_status = br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?' +- ++_control_chars = re.compile(b'[\x00-\x1F\x7F]') + + + class IMAP4: +@@ -994,6 +994,8 @@ def _command(self, name, *args): + if arg is None: continue + if isinstance(arg, str): + arg = bytes(arg, self._encoding) ++ if _control_chars.search(arg): ++ raise ValueError("Control characters not allowed in commands") + data = data + b' ' + arg + + literal = self.literal +diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py +index f817707743..9ce59b3040 100644 +--- a/Lib/test/test_imaplib.py ++++ b/Lib/test/test_imaplib.py +@@ -505,6 +505,12 @@ def test_login(self): + self.assertEqual(data[0], b'LOGIN completed') + self.assertEqual(client.state, 'AUTH') + ++ def test_control_characters(self): ++ client, _ = self._setup(SimpleIMAPHandler) ++ for c0 in support.control_characters_c0(): ++ with self.assertRaises(ValueError): ++ client.login(f'user{c0}', 'pass') ++ + def test_logout(self): + client, _ = self._setup(SimpleIMAPHandler) + typ, data = client.login('user', 'pass') +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst +new file mode 100644 +index 0000000000..4e13fe92bc +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-41-06.gh-issue-143921.AeCOor.rst +@@ -0,0 +1 @@ ++Reject control characters in IMAP commands. diff --git a/00475-cve-2025-15367.patch b/00475-cve-2025-15367.patch new file mode 100644 index 0000000..9a64894 --- /dev/null +++ b/00475-cve-2025-15367.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Tue, 20 Jan 2026 14:46:32 -0600 +Subject: 00475: CVE-2025-15367 + +gh-143923: Reject control characters in POP3 commands + +(cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) +--- + Lib/poplib.py | 2 ++ + Lib/test/test_poplib.py | 8 ++++++++ + .../2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst | 1 + + 3 files changed, 11 insertions(+) + create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst + +diff --git a/Lib/poplib.py b/Lib/poplib.py +index 0f8587317c..f563030f7f 100644 +--- a/Lib/poplib.py ++++ b/Lib/poplib.py +@@ -122,6 +122,8 @@ def _putline(self, line): + def _putcmd(self, line): + if self._debugging: print('*cmd*', repr(line)) + line = bytes(line, self.encoding) ++ if re.search(b'[\x00-\x1F\x7F]', line): ++ raise ValueError('Control characters not allowed in commands') + self._putline(line) + + +diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py +index 1220ca32ef..2655e366fd 100644 +--- a/Lib/test/test_poplib.py ++++ b/Lib/test/test_poplib.py +@@ -12,6 +12,7 @@ + import unittest + from unittest import TestCase, skipUnless + from test import support as test_support ++from test.support import control_characters_c0 + from test.support import hashlib_helper + from test.support import socket_helper + from test.support import threading_helper +@@ -365,6 +366,13 @@ def test_quit(self): + self.assertIsNone(self.client.sock) + self.assertIsNone(self.client.file) + ++ def test_control_characters(self): ++ for c0 in control_characters_c0(): ++ with self.assertRaises(ValueError): ++ self.client.user(f'user{c0}') ++ with self.assertRaises(ValueError): ++ self.client.pass_(f'{c0}pass') ++ + @requires_ssl + def test_stls_capa(self): + capa = self.client.capa() +diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +new file mode 100644 +index 0000000000..3cde4df3e0 +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-01-16-11-43-47.gh-issue-143923.DuytMe.rst +@@ -0,0 +1 @@ ++Reject control characters in POP3 commands. diff --git a/python3.10.spec b/python3.10.spec index de79e10..0a4531b 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python-2.0.1 @@ -350,6 +350,31 @@ Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch # stressed on OpenSSL 3.5. Patch462: 00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch +# 00473 # e0df4af4663a200a370a7c7b2391588396bcf20f +# CVE-2026-0865 +# +# gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) +# +# * Add 'test.support' fixture for C0 control characters +# * gh-143916: Reject control characters in wsgiref.headers.Headers +Patch473: 00473-cve-2026-0865.patch + +# 00474 # 837ddca0372fa87ff9cee47142200caa21e77def +# CVE-2025-15366 +# +# gh-143921: Reject control characters in IMAP commands +# +# (cherry-picked from commit 6262704b134db2a4ba12e85ecfbd968534f28b45) +Patch474: 00474-cve-2025-15366.patch + +# 00475 # 3748209a316662d4e85981ca1a7418547a1d25c6 +# CVE-2025-15367 +# +# gh-143923: Reject control characters in POP3 commands +# +# (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) +Patch475: 00475-cve-2025-15367.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1649,6 +1674,9 @@ CheckPython optimized # ====================================================== %changelog +* Mon Feb 09 2026 Tomáš Hrnčiar - 3.10.19-4 +- Security fixes for CVE-2026-0865, CVE-2025-15366 and CVE-2025-15367 + * Sat Jan 17 2026 Fedora Release Engineering - 3.10.19-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild From c9e6166456a3fea8d2a44bb6ecdb528bd274e8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hrn=C4=8Diar?= Date: Tue, 3 Mar 2026 14:17:40 +0100 Subject: [PATCH 105/112] Update to 3.10.20 --- ..._seterror-handling-ssl_error_syscall.patch | 2 +- 00473-cve-2026-0865.patch | 90 ------------------- python3.10.spec | 16 ++-- sources | 4 +- 4 files changed, 8 insertions(+), 104 deletions(-) delete mode 100644 00473-cve-2026-0865.patch diff --git a/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch b/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch index 5c0cda1..fcf142f 100644 --- a/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch +++ b/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch @@ -102,7 +102,7 @@ index 0000000000..75d926ab59 +Fix the :mod:`ssl` module error handling of connection terminate by peer. +It now throws an OSError with the appropriate error code instead of an EOFError. diff --git a/Modules/_ssl.c b/Modules/_ssl.c -index 6852cc363b..91bf27bfef 100644 +index 3bd8b96dcc..6f5fb23b8b 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -582,7 +582,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) { diff --git a/00473-cve-2026-0865.patch b/00473-cve-2026-0865.patch deleted file mode 100644 index 3504e6b..0000000 --- a/00473-cve-2026-0865.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Seth Michael Larson -Date: Sat, 17 Jan 2026 11:46:21 -0600 -Subject: 00473: CVE-2026-0865 - - gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) - -* Add 'test.support' fixture for C0 control characters -* gh-143916: Reject control characters in wsgiref.headers.Headers ---- - Lib/test/support/__init__.py | 7 +++++++ - Lib/test/test_wsgiref.py | 12 +++++++++++- - Lib/wsgiref/headers.py | 3 +++ - .../2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst | 2 ++ - 4 files changed, 23 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst - -diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py -index 0d3b9634f1..d0492fe191 100644 ---- a/Lib/test/support/__init__.py -+++ b/Lib/test/support/__init__.py -@@ -2157,3 +2157,10 @@ def adjust_int_max_str_digits(max_digits): - yield - finally: - sys.set_int_max_str_digits(current) -+ -+ -+def control_characters_c0() -> list[str]: -+ """Returns a list of C0 control characters as strings. -+ C0 control characters defined as the byte range 0x00-0x1F, and 0x7F. -+ """ -+ return [chr(c) for c in range(0x00, 0x20)] + ["\x7F"] -diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py -index 42094f4677..01ca51ba45 100644 ---- a/Lib/test/test_wsgiref.py -+++ b/Lib/test/test_wsgiref.py -@@ -1,6 +1,6 @@ - from unittest import mock - from test import support --from test.support import socket_helper -+from test.support import socket_helper, control_characters_c0 - from test.support import warnings_helper - from test.test_httpservers import NoLogRequestHandler - from unittest import TestCase -@@ -527,6 +527,16 @@ def testExtras(self): - '\r\n' - ) - -+ def testRaisesControlCharacters(self): -+ headers = Headers() -+ for c0 in control_characters_c0(): -+ self.assertRaises(ValueError, headers.__setitem__, f"key{c0}", "val") -+ self.assertRaises(ValueError, headers.__setitem__, "key", f"val{c0}") -+ self.assertRaises(ValueError, headers.add_header, f"key{c0}", "val", param="param") -+ self.assertRaises(ValueError, headers.add_header, "key", f"val{c0}", param="param") -+ self.assertRaises(ValueError, headers.add_header, "key", "val", param=f"param{c0}") -+ -+ - class ErrorHandler(BaseCGIHandler): - """Simple handler subclass for testing BaseHandler""" - -diff --git a/Lib/wsgiref/headers.py b/Lib/wsgiref/headers.py -index fab851c5a4..fd98e85d75 100644 ---- a/Lib/wsgiref/headers.py -+++ b/Lib/wsgiref/headers.py -@@ -9,6 +9,7 @@ - # existence of which force quoting of the parameter value. - import re - tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') -+_control_chars_re = re.compile(r'[\x00-\x1F\x7F]') - - def _formatparam(param, value=None, quote=1): - """Convenience function to format and return a key=value pair. -@@ -41,6 +42,8 @@ def __init__(self, headers=None): - def _convert_string_type(self, value): - """Convert/check value type.""" - if type(value) is str: -+ if _control_chars_re.search(value): -+ raise ValueError("Control characters not allowed in headers") - return value - raise AssertionError("Header names/values must be" - " of type str (got {0})".format(repr(value))) -diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst -new file mode 100644 -index 0000000000..44bd0b2705 ---- /dev/null -+++ b/Misc/NEWS.d/next/Security/2026-01-16-11-07-36.gh-issue-143916.dpWeOD.rst -@@ -0,0 +1,2 @@ -+Reject C0 control characters within wsgiref.headers.Headers fields, values, -+and parameters. diff --git a/python3.10.spec b/python3.10.spec index 0a4531b..ddee0fe 100644 --- a/python3.10.spec +++ b/python3.10.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}.20 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -350,15 +350,6 @@ Patch452: 00452-properly-apply-exported-cflags-for-dtrace-systemtap-builds.patch # stressed on OpenSSL 3.5. Patch462: 00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch -# 00473 # e0df4af4663a200a370a7c7b2391588396bcf20f -# CVE-2026-0865 -# -# gh-143916: Reject control characters in wsgiref.headers.Headers (GH-143917) -# -# * Add 'test.support' fixture for C0 control characters -# * gh-143916: Reject control characters in wsgiref.headers.Headers -Patch473: 00473-cve-2026-0865.patch - # 00474 # 837ddca0372fa87ff9cee47142200caa21e77def # CVE-2025-15366 # @@ -1674,6 +1665,9 @@ CheckPython optimized # ====================================================== %changelog +* Tue Mar 03 2026 Tomáš Hrnčiar - 3.10.20-1 +- Update to 3.10.20 + * Mon Feb 09 2026 Tomáš Hrnčiar - 3.10.19-4 - Security fixes for CVE-2026-0865, CVE-2025-15366 and CVE-2025-15367 diff --git a/sources b/sources index 6de6cda..073dea3 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.19.tar.xz) = 9ea1e952bb5f7c9cc8d3efd8e7ae0059c129b6e09d12ded7d4e22476fad35f2c8186b1e003ea35a0099ffa5ff0a114985c3e960fba84e7037670b840a3e19c68 -SHA512 (Python-3.10.19.tar.xz.asc) = 64bcee68c2f4e0718daaf19d405f4a5bd0ce3fc3d13bb5cbae8d4a36e419dd104c94323b497f1d06110f6b62a1b3b351279c534145f4e8cea9af0d7bb0a8b5c9 +SHA512 (Python-3.10.20.tar.xz) = 591d3acf7ef47307b8c58fec9516731b374bcdf6eb21883410f67402f823a183f1abffec1116583e394610730f414d5a98b4c3437ea5174a4d2adbb99b8f6e5b +SHA512 (Python-3.10.20.tar.xz.asc) = cb90ce514c63c63adc10cbb3db778eae626b922461715954daf08b3a3a99b8b4c750fded624787b7d28fc10a203b0e0e5494b91e5305ef56a23fda46c023c203 From 458effe6fa67601a6c8dbc89c8ea31630a0cdb54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 9 Apr 2026 13:16:25 +0200 Subject: [PATCH 106/112] Explicitly build with OpenSSL 3 for now https://fedoraproject.org/wiki/Changes/OpenSSL40 --- python3.10.spec | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/python3.10.spec b/python3.10.spec index ddee0fe..b076721 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python-2.0.1 @@ -216,7 +216,6 @@ BuildRequires: make BuildRequires: mpdecimal-devel BuildRequires: ncurses-devel -BuildRequires: openssl-devel BuildRequires: pkgconfig BuildRequires: readline-devel BuildRequires: redhat-rpm-config >= 127 @@ -229,6 +228,10 @@ BuildRequires: tix-devel BuildRequires: tk-devel < 1:9 BuildRequires: tzdata +# Support for OpenSSL 4 only landed in Python 3.15 for now +# https://github.com/python/cpython/issues/146207 +BuildRequires: (openssl-devel < 1:4 or openssl3-devel) + %if %{with valgrind} BuildRequires: valgrind-devel %endif @@ -1665,6 +1668,9 @@ CheckPython optimized # ====================================================== %changelog +* Sat Apr 11 2026 Miro Hrončok - 3.10.20-2 +- Explicitly build with OpenSSL 3 + * Tue Mar 03 2026 Tomáš Hrnčiar - 3.10.20-1 - Update to 3.10.20 From 16aa6aa9ffefb7c724be998444c3d6a41f393827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 2 Jul 2026 10:59:38 +0200 Subject: [PATCH 107/112] Fix ssl.SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data with OpenSSL 3.5.7+ --- 00489-openssl-3.5.7.patch | 75 +++++++++++++++++++++++++++++++++++++++ python3.10.spec | 13 +++++++ 2 files changed, 88 insertions(+) create mode 100644 00489-openssl-3.5.7.patch diff --git a/00489-openssl-3.5.7.patch b/00489-openssl-3.5.7.patch new file mode 100644 index 0000000..ea5bf03 --- /dev/null +++ b/00489-openssl-3.5.7.patch @@ -0,0 +1,75 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: David Benjamin +Date: Fri, 24 Mar 2023 09:04:30 -0400 +Subject: 00489: Use BIO_eof to detect EOF for SSL_FILETYPE_ASN1 + +In PEM, we need to parse until error and then suppress `PEM_R_NO_START_LINE`, because PEM allows arbitrary leading and trailing data. DER, however, does not. Parsing until error and suppressing `ASN1_R_HEADER_TOO_LONG` doesn't quite work because that error also covers some cases that should be rejected. + +Instead, check `BIO_eof` early and stop the loop that way. + +This fixes https://github.com/python/cpython/issues/151504 and adds compatibility with OpenSSL 3.5.7+ + +(cherry-picked from commit acfe02f3b05436658d92add6b168538b30f357f0) +--- + Lib/test/test_ssl.py | 2 ++ + .../2022-12-20-10-55-14.gh-issue-100372.utfP65.rst | 2 ++ + Modules/_ssl.c | 10 ++++++---- + 3 files changed, 10 insertions(+), 4 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 21d3676c22..f772bd6ab6 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -1533,6 +1533,8 @@ def test_load_verify_cadata(self): + "not enough data: cadata does not contain a certificate" + ): + ctx.load_verify_locations(cadata=b"broken") ++ with self.assertRaises(ssl.SSLError): ++ ctx.load_verify_locations(cadata=cacert_der + b"A") + + @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") + def test_load_dh_params(self): +diff --git a/Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst b/Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst +new file mode 100644 +index 0000000000..ec37aff509 +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst +@@ -0,0 +1,2 @@ ++:meth:`ssl.SSLContext.load_verify_locations` no longer incorrectly accepts ++some cases of trailing data when parsing DER. +diff --git a/Modules/_ssl.c b/Modules/_ssl.c +index 6f5fb23b8b..7b3cf61474 100644 +--- a/Modules/_ssl.c ++++ b/Modules/_ssl.c +@@ -3949,7 +3949,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, + { + BIO *biobuf = NULL; + X509_STORE *store; +- int retval = -1, err, loaded = 0; ++ int retval = -1, err, loaded = 0, was_bio_eof = 0; + + assert(filetype == SSL_FILETYPE_ASN1 || filetype == SSL_FILETYPE_PEM); + +@@ -3977,6 +3977,10 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, + int r; + + if (filetype == SSL_FILETYPE_ASN1) { ++ if (BIO_eof(biobuf)) { ++ was_bio_eof = 1; ++ break; ++ } + cert = d2i_X509_bio(biobuf, NULL); + } else { + cert = PEM_read_bio_X509(biobuf, NULL, +@@ -4012,9 +4016,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, + } + _setSSLError(get_state_ctx(self), msg, 0, __FILE__, __LINE__); + retval = -1; +- } else if ((filetype == SSL_FILETYPE_ASN1) && +- (ERR_GET_LIB(err) == ERR_LIB_ASN1) && +- (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG)) { ++ } else if ((filetype == SSL_FILETYPE_ASN1) && was_bio_eof) { + /* EOF ASN1 file, not an error */ + ERR_clear_error(); + retval = 0; diff --git a/python3.10.spec b/python3.10.spec index b076721..53f3806 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -369,6 +369,18 @@ Patch474: 00474-cve-2025-15366.patch # (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) Patch475: 00475-cve-2025-15367.patch +# 00489 # 008af720a5f6f98ed3feb8ebdbf88ab9dea4db22 +# Use BIO_eof to detect EOF for SSL_FILETYPE_ASN1 +# +# In PEM, we need to parse until error and then suppress `PEM_R_NO_START_LINE`, because PEM allows arbitrary leading and trailing data. DER, however, does not. Parsing until error and suppressing `ASN1_R_HEADER_TOO_LONG` doesn't quite work because that error also covers some cases that should be rejected. +# +# Instead, check `BIO_eof` early and stop the loop that way. +# +# This fixes https://github.com/python/cpython/issues/151504 and adds compatibility with OpenSSL 3.5.7+ +# +# (cherry-picked from commit acfe02f3b05436658d92add6b168538b30f357f0) +Patch489: 00489-openssl-3.5.7.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1670,6 +1682,7 @@ CheckPython optimized %changelog * Sat Apr 11 2026 Miro Hrončok - 3.10.20-2 - Explicitly build with OpenSSL 3 +- Fix ssl.SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data with OpenSSL 3.5.7+ * Tue Mar 03 2026 Tomáš Hrnčiar - 3.10.20-1 - Update to 3.10.20 From e6d9413cd5d26f89148ae857642b9a1921465822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lum=C3=ADr=20Balhar?= Date: Wed, 1 Jul 2026 10:55:23 +0000 Subject: [PATCH 108/112] Run a new test to monitor changes in required symbols Co-Authored-By: Claude Sonnet 4.6 (1M context) --- plan.fmf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plan.fmf b/plan.fmf index 71f3e63..88053e4 100644 --- a/plan.fmf +++ b/plan.fmf @@ -34,6 +34,9 @@ discover: - name: marshalparser path: /marshalparser test: "VERSION=${pybasever} SAMPLE=10 ./test_marshalparser_compatibility.sh" + - name: required_symbols + path: /required-symbols + test: "VERSION=${pybasever} ./check.sh" prepare: - name: Install dependencies @@ -50,8 +53,9 @@ prepare: - virtualenv # for virtualenv tests - glibc-all-langpacks # for locale tests - marshalparser # for testing compatibility (magic numbers) with marshalparser + - binutils # for nm (symbol inspection) - rpm # for debugging - - dnf # for upgrade + - dnf # for upgrade and downgrade - name: Update packages how: shell script: dnf upgrade -y From c30eb404789121d3ed86e736ccdf5952df55279a Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 16 Jul 2026 22:47:20 +0000 Subject: [PATCH 109/112] Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild --- python3.10.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python3.10.spec b/python3.10.spec index 53f3806..85c416e 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python-2.0.1 @@ -1680,6 +1680,9 @@ CheckPython optimized # ====================================================== %changelog +* Thu Jul 16 2026 Fedora Release Engineering - 3.10.20-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild + * Sat Apr 11 2026 Miro Hrončok - 3.10.20-2 - Explicitly build with OpenSSL 3 - Fix ssl.SSLError: [ASN1: NOT_ENOUGH_DATA] not enough data with OpenSSL 3.5.7+ From 7da201e90094c47501dcb1ee89872aef1884f4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Thu, 30 Jul 2026 17:25:58 +0200 Subject: [PATCH 110/112] Skip UDP Lite tests if it's not supported - Fixes FTBFS on Linux kernel 7.1 and newer --- ...udp-lite-tests-if-it-s-not-supported.patch | 64 +++++++++++++++++++ python3.10.spec | 13 +++- 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch diff --git a/00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch b/00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch new file mode 100644 index 0000000..bf0a459 --- /dev/null +++ b/00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch @@ -0,0 +1,64 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Victor Stinner +Date: Wed, 13 May 2026 17:27:56 +0200 +Subject: 00491: gh-149776: Skip UDP Lite tests if it's not supported + +Fix test_socket on Linux kernel 7.1 and newer: skip UDP Lite tests if +it's not supported. + +(cherry picked from commit 3cfc249e11a132dc69624150843779aa96c72b2b) +(cherry picked from commit 49d08674d8dba50dc29539e3c7bce21d66066b06) +--- + Lib/test/test_socket.py | 22 ++++++++++++++++++- + ...-05-13-14-53-23.gh-issue-149776.orqgsn.rst | 2 ++ + 2 files changed, 23 insertions(+), 1 deletion(-) + create mode 100644 Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst + +diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py +index 15f7fb4a80..4a3d8f7ce6 100644 +--- a/Lib/test/test_socket.py ++++ b/Lib/test/test_socket.py +@@ -142,6 +142,26 @@ def _have_socket_bluetooth(): + return True + + ++def _have_udp_lite(): ++ if not hasattr(socket, "IPPROTO_UDPLITE"): ++ return False ++ # Older Android versions block UDPLITE with SELinux. ++ if support.is_android and platform.android_ver().api_level < 29: ++ return False ++ ++ try: ++ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDPLITE) ++ except OSError as exc: ++ # Linux 7.1 removed UDP Lite support ++ if exc.errno == errno.EPROTONOSUPPORT: ++ return False ++ raise ++ sock.close() ++ ++ return True ++ ++ ++ + @contextlib.contextmanager + def socket_setdefaulttimeout(timeout): + old_timeout = socket.getdefaulttimeout() +@@ -166,7 +186,7 @@ def socket_setdefaulttimeout(timeout): + + HAVE_SOCKET_VSOCK = _have_socket_vsock() + +-HAVE_SOCKET_UDPLITE = hasattr(socket, "IPPROTO_UDPLITE") ++HAVE_SOCKET_UDPLITE = _have_udp_lite() + + HAVE_SOCKET_BLUETOOTH = _have_socket_bluetooth() + +diff --git a/Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst b/Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst +new file mode 100644 +index 0000000000..e86a9130ff +--- /dev/null ++++ b/Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst +@@ -0,0 +1,2 @@ ++Fix test_socket on Linux kernel 7.1 and newer: skip UDP Lite tests if it's ++not supported. Patch by Victor Stinner. diff --git a/python3.10.spec b/python3.10.spec index 85c416e..d06a2f6 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 3%{?dist} +Release: 4%{?dist} License: Python-2.0.1 @@ -381,6 +381,13 @@ Patch475: 00475-cve-2025-15367.patch # (cherry-picked from commit acfe02f3b05436658d92add6b168538b30f357f0) Patch489: 00489-openssl-3.5.7.patch +# 00491 # ac14737379922303720216b61803474c84f291ef +# gh-149776: Skip UDP Lite tests if it's not supported +# +# Fix test_socket on Linux kernel 7.1 and newer: skip UDP Lite tests if +# it's not supported. +Patch491: 00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora, EL, etc., @@ -1680,6 +1687,10 @@ CheckPython optimized # ====================================================== %changelog +* Thu Jul 30 2026 Miro Hrončok - 3.10.20-4 + - Skip UDP Lite tests if it's not supported + - Fixes FTBFS on Linux kernel 7.1 and newer + * Thu Jul 16 2026 Fedora Release Engineering - 3.10.20-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild From b4205523e70d79d5be55bc4d9368bbe1cbceddcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 11 Mar 2026 19:39:18 +0100 Subject: [PATCH 111/112] Only explicitly require expat >= installed version when expat < 2.7.4 See https://src.fedoraproject.org/rpms/expat/c/4da0543472 (cherry picked from python3.15 commit ce1bde3e67443b7cf5df33bf58cb2ec75cc2c8e2) --- python3.10.spec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python3.10.spec b/python3.10.spec index d06a2f6..97d0e29 100644 --- a/python3.10.spec +++ b/python3.10.spec @@ -545,8 +545,12 @@ Requires: tzdata # We avoid this problem by requiring at least the same version of expat that # was used during the build time. # Other subpackages (like -debug) also need this, but they all depend on -libs. +# Since expat 2.7.4, the library has versioned symbols and this is no longer needed, +# as the generated requirement will be in the form of libexpat.so.1(LIBEXPAT_2.7.2) etc. %global expat_version %(LANG=C rpm -q --qf '%%{version}' expat.%{_target_cpu} | sed 's/.*not installed/0/') +%if v"%{expat_version}" < v"2.7.4" Requires: expat%{?_isa} >= %{expat_version} +%endif # Since patch 251 changed from distutils to sysconfig, pip needed to be adapted From daba5b738caf36d3903f98c1c65be5efbcfa658a Mon Sep 17 00:00:00 2001 From: Karolina Surma Date: Thu, 13 Aug 2026 12:14:24 +0200 Subject: [PATCH 112/112] Update to Python 3.10.21 --- ..._seterror-handling-ssl_error_syscall.patch | 10 +-- 00489-openssl-3.5.7.patch | 75 ------------------- ...udp-lite-tests-if-it-s-not-supported.patch | 64 ---------------- ...-test_large_content_length_truncated.patch | 23 ++++++ python3.10.spec | 28 +++---- sources | 4 +- 6 files changed, 39 insertions(+), 165 deletions(-) delete mode 100644 00489-openssl-3.5.7.patch delete mode 100644 00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch create mode 100644 00494-increase-the-timeout-of-test_large_content_length_truncated.patch diff --git a/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch b/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch index fcf142f..1eaf3a2 100644 --- a/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch +++ b/00462-fix-pyssl_seterror-handling-ssl_error_syscall.patch @@ -22,10 +22,10 @@ Co-authored-by: Petr Viktorin create mode 100644 Misc/NEWS.d/next/Library/2024-02-18-09-50-31.gh-issue-115627.HGchj0.rst diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py -index 0f1397de73..21d3676c22 100644 +index f4bba8ff03..f772bd6ab6 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py -@@ -2605,16 +2605,18 @@ def run(self): +@@ -2607,16 +2607,18 @@ def run(self): self.write(msg.lower()) except OSError as e: # handles SSLError and socket errors @@ -53,7 +53,7 @@ index 0f1397de73..21d3676c22 100644 try: self.write(b"ERROR\n") except OSError: -@@ -3296,23 +3298,16 @@ def test_wrong_cert_tls13(self): +@@ -3298,23 +3300,16 @@ def test_wrong_cert_tls13(self): client_context.wrap_socket(socket.socket(), server_hostname=hostname, suppress_ragged_eofs=False) as s: @@ -82,7 +82,7 @@ index 0f1397de73..21d3676c22 100644 def test_rude_shutdown(self): """A brutal shutdown of an SSL server should raise an OSError -@@ -4558,8 +4553,8 @@ def msg_cb(conn, direction, version, content_type, msg_type, data): +@@ -4560,8 +4555,8 @@ def msg_cb(conn, direction, version, content_type, msg_type, data): # test sometimes fails with EOF error. Test passes as long as # server aborts connection with an error. with self.assertRaisesRegex( @@ -102,7 +102,7 @@ index 0000000000..75d926ab59 +Fix the :mod:`ssl` module error handling of connection terminate by peer. +It now throws an OSError with the appropriate error code instead of an EOFError. diff --git a/Modules/_ssl.c b/Modules/_ssl.c -index 3bd8b96dcc..6f5fb23b8b 100644 +index af770c7f18..7b3cf61474 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -582,7 +582,7 @@ PySSL_ChainExceptions(PySSLSocket *sslsock) { diff --git a/00489-openssl-3.5.7.patch b/00489-openssl-3.5.7.patch deleted file mode 100644 index ea5bf03..0000000 --- a/00489-openssl-3.5.7.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: David Benjamin -Date: Fri, 24 Mar 2023 09:04:30 -0400 -Subject: 00489: Use BIO_eof to detect EOF for SSL_FILETYPE_ASN1 - -In PEM, we need to parse until error and then suppress `PEM_R_NO_START_LINE`, because PEM allows arbitrary leading and trailing data. DER, however, does not. Parsing until error and suppressing `ASN1_R_HEADER_TOO_LONG` doesn't quite work because that error also covers some cases that should be rejected. - -Instead, check `BIO_eof` early and stop the loop that way. - -This fixes https://github.com/python/cpython/issues/151504 and adds compatibility with OpenSSL 3.5.7+ - -(cherry-picked from commit acfe02f3b05436658d92add6b168538b30f357f0) ---- - Lib/test/test_ssl.py | 2 ++ - .../2022-12-20-10-55-14.gh-issue-100372.utfP65.rst | 2 ++ - Modules/_ssl.c | 10 ++++++---- - 3 files changed, 10 insertions(+), 4 deletions(-) - create mode 100644 Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst - -diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py -index 21d3676c22..f772bd6ab6 100644 ---- a/Lib/test/test_ssl.py -+++ b/Lib/test/test_ssl.py -@@ -1533,6 +1533,8 @@ def test_load_verify_cadata(self): - "not enough data: cadata does not contain a certificate" - ): - ctx.load_verify_locations(cadata=b"broken") -+ with self.assertRaises(ssl.SSLError): -+ ctx.load_verify_locations(cadata=cacert_der + b"A") - - @unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows") - def test_load_dh_params(self): -diff --git a/Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst b/Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst -new file mode 100644 -index 0000000000..ec37aff509 ---- /dev/null -+++ b/Misc/NEWS.d/next/Library/2022-12-20-10-55-14.gh-issue-100372.utfP65.rst -@@ -0,0 +1,2 @@ -+:meth:`ssl.SSLContext.load_verify_locations` no longer incorrectly accepts -+some cases of trailing data when parsing DER. -diff --git a/Modules/_ssl.c b/Modules/_ssl.c -index 6f5fb23b8b..7b3cf61474 100644 ---- a/Modules/_ssl.c -+++ b/Modules/_ssl.c -@@ -3949,7 +3949,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, - { - BIO *biobuf = NULL; - X509_STORE *store; -- int retval = -1, err, loaded = 0; -+ int retval = -1, err, loaded = 0, was_bio_eof = 0; - - assert(filetype == SSL_FILETYPE_ASN1 || filetype == SSL_FILETYPE_PEM); - -@@ -3977,6 +3977,10 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, - int r; - - if (filetype == SSL_FILETYPE_ASN1) { -+ if (BIO_eof(biobuf)) { -+ was_bio_eof = 1; -+ break; -+ } - cert = d2i_X509_bio(biobuf, NULL); - } else { - cert = PEM_read_bio_X509(biobuf, NULL, -@@ -4012,9 +4016,7 @@ _add_ca_certs(PySSLContext *self, const void *data, Py_ssize_t len, - } - _setSSLError(get_state_ctx(self), msg, 0, __FILE__, __LINE__); - retval = -1; -- } else if ((filetype == SSL_FILETYPE_ASN1) && -- (ERR_GET_LIB(err) == ERR_LIB_ASN1) && -- (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG)) { -+ } else if ((filetype == SSL_FILETYPE_ASN1) && was_bio_eof) { - /* EOF ASN1 file, not an error */ - ERR_clear_error(); - retval = 0; diff --git a/00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch b/00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch deleted file mode 100644 index bf0a459..0000000 --- a/00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Victor Stinner -Date: Wed, 13 May 2026 17:27:56 +0200 -Subject: 00491: gh-149776: Skip UDP Lite tests if it's not supported - -Fix test_socket on Linux kernel 7.1 and newer: skip UDP Lite tests if -it's not supported. - -(cherry picked from commit 3cfc249e11a132dc69624150843779aa96c72b2b) -(cherry picked from commit 49d08674d8dba50dc29539e3c7bce21d66066b06) ---- - Lib/test/test_socket.py | 22 ++++++++++++++++++- - ...-05-13-14-53-23.gh-issue-149776.orqgsn.rst | 2 ++ - 2 files changed, 23 insertions(+), 1 deletion(-) - create mode 100644 Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst - -diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py -index 15f7fb4a80..4a3d8f7ce6 100644 ---- a/Lib/test/test_socket.py -+++ b/Lib/test/test_socket.py -@@ -142,6 +142,26 @@ def _have_socket_bluetooth(): - return True - - -+def _have_udp_lite(): -+ if not hasattr(socket, "IPPROTO_UDPLITE"): -+ return False -+ # Older Android versions block UDPLITE with SELinux. -+ if support.is_android and platform.android_ver().api_level < 29: -+ return False -+ -+ try: -+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDPLITE) -+ except OSError as exc: -+ # Linux 7.1 removed UDP Lite support -+ if exc.errno == errno.EPROTONOSUPPORT: -+ return False -+ raise -+ sock.close() -+ -+ return True -+ -+ -+ - @contextlib.contextmanager - def socket_setdefaulttimeout(timeout): - old_timeout = socket.getdefaulttimeout() -@@ -166,7 +186,7 @@ def socket_setdefaulttimeout(timeout): - - HAVE_SOCKET_VSOCK = _have_socket_vsock() - --HAVE_SOCKET_UDPLITE = hasattr(socket, "IPPROTO_UDPLITE") -+HAVE_SOCKET_UDPLITE = _have_udp_lite() - - HAVE_SOCKET_BLUETOOTH = _have_socket_bluetooth() - -diff --git a/Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst b/Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst -new file mode 100644 -index 0000000000..e86a9130ff ---- /dev/null -+++ b/Misc/NEWS.d/next/Tests/2026-05-13-14-53-23.gh-issue-149776.orqgsn.rst -@@ -0,0 +1,2 @@ -+Fix test_socket on Linux kernel 7.1 and newer: skip UDP Lite tests if it's -+not supported. Patch by Victor Stinner. diff --git a/00494-increase-the-timeout-of-test_large_content_length_truncated.patch b/00494-increase-the-timeout-of-test_large_content_length_truncated.patch new file mode 100644 index 0000000..58ffd5d --- /dev/null +++ b/00494-increase-the-timeout-of-test_large_content_length_truncated.patch @@ -0,0 +1,23 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Karolina Surma +Date: Fri, 14 Aug 2026 09:38:26 +0200 +Subject: 00494: Increase the timeout of test_large_content_length_truncated + +It has started to fail randomly when run on s390x architecture. +--- + Lib/test/test_httpservers.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py +index 5eb3c82fbd..aa8ad1c323 100644 +--- a/Lib/test/test_httpservers.py ++++ b/Lib/test/test_httpservers.py +@@ -872,7 +872,7 @@ def test_large_content_length(self): + self.assertEqual(res.read(), b'%d %d' % (size, size) + self.linesep) + + def test_large_content_length_truncated(self): +- with support.swap_attr(self.request_handler, 'timeout', 0.001): ++ with support.swap_attr(self.request_handler, 'timeout', support.LOOPBACK_TIMEOUT): + for w in range(18, 65): + size = 1 << w + headers = {'Content-Length' : str(size)} diff --git a/python3.10.spec b/python3.10.spec index 97d0e29..3378bf7 100644 --- a/python3.10.spec +++ b/python3.10.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}.20 +%global general_version %{pybasever}.21 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 4%{?dist} +Release: 1%{?dist} License: Python-2.0.1 @@ -369,24 +369,11 @@ Patch474: 00474-cve-2025-15366.patch # (cherry-picked from commit b234a2b67539f787e191d2ef19a7cbdce32874e7) Patch475: 00475-cve-2025-15367.patch -# 00489 # 008af720a5f6f98ed3feb8ebdbf88ab9dea4db22 -# Use BIO_eof to detect EOF for SSL_FILETYPE_ASN1 +# 00494 # 430aab133397ed44cc9ee621fd311e02fee317b5 +# Increase the timeout of test_large_content_length_truncated # -# In PEM, we need to parse until error and then suppress `PEM_R_NO_START_LINE`, because PEM allows arbitrary leading and trailing data. DER, however, does not. Parsing until error and suppressing `ASN1_R_HEADER_TOO_LONG` doesn't quite work because that error also covers some cases that should be rejected. -# -# Instead, check `BIO_eof` early and stop the loop that way. -# -# This fixes https://github.com/python/cpython/issues/151504 and adds compatibility with OpenSSL 3.5.7+ -# -# (cherry-picked from commit acfe02f3b05436658d92add6b168538b30f357f0) -Patch489: 00489-openssl-3.5.7.patch - -# 00491 # ac14737379922303720216b61803474c84f291ef -# gh-149776: Skip UDP Lite tests if it's not supported -# -# Fix test_socket on Linux kernel 7.1 and newer: skip UDP Lite tests if -# it's not supported. -Patch491: 00491-gh-149776-skip-udp-lite-tests-if-it-s-not-supported.patch +# It has started to fail randomly when run on s390x architecture. +Patch494: 00494-increase-the-timeout-of-test_large_content_length_truncated.patch # (New patches go here ^^^) # @@ -1691,6 +1678,9 @@ CheckPython optimized # ====================================================== %changelog +* Thu Aug 13 2026 Karolina Surma - 3.10.21-1 +- Update to Python 3.10.21 + * Thu Jul 30 2026 Miro Hrončok - 3.10.20-4 - Skip UDP Lite tests if it's not supported - Fixes FTBFS on Linux kernel 7.1 and newer diff --git a/sources b/sources index 073dea3..1833fd0 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (Python-3.10.20.tar.xz) = 591d3acf7ef47307b8c58fec9516731b374bcdf6eb21883410f67402f823a183f1abffec1116583e394610730f414d5a98b4c3437ea5174a4d2adbb99b8f6e5b -SHA512 (Python-3.10.20.tar.xz.asc) = cb90ce514c63c63adc10cbb3db778eae626b922461715954daf08b3a3a99b8b4c750fded624787b7d28fc10a203b0e0e5494b91e5305ef56a23fda46c023c203 +SHA512 (Python-3.10.21.tar.xz) = 6f6de7c5e4c0457f2d189ed5d111c83fb8775e19123afe4f9fd0ae2b93f3fa2bbb7ad849ade6bb5227d4a6a3d63abc8e167fbe5fb54fa715660c89fd6274daee +SHA512 (Python-3.10.21.tar.xz.asc) = 72d6aeaa0f51e527f82392cf1f969b0ad50a48fe10e8b7e5feb6117718223d00757f7b375b3ac82e257571d5a61f8162e9dd59b81fcf8f2a441c6deb42be71cb