diff --git a/.gitignore b/.gitignore index c76fff1..eba831d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/Python-3.8.17-noexe.tar.xz +SOURCES/Python-3.8.6-noexe.tar.xz diff --git a/.python38.metadata b/.python38.metadata index 060653b..a2673b8 100644 --- a/.python38.metadata +++ b/.python38.metadata @@ -1 +1 @@ -5ecdca78a141bb6d7e13732920886affd7338fca SOURCES/Python-3.8.17-noexe.tar.xz +e77d08894869ecf483e9f945663f75316ad68bf1 SOURCES/Python-3.8.6-noexe.tar.xz diff --git a/SOURCES/00189-use-rpm-wheels.patch b/SOURCES/00189-use-rpm-wheels.patch index 521efef..0485fdc 100644 --- a/SOURCES/00189-use-rpm-wheels.patch +++ b/SOURCES/00189-use-rpm-wheels.patch @@ -1,4 +1,4 @@ -From ff07393a8c9c3d69090a775a8d4b89a3019f71a9 Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 15 Aug 2018 15:36:29 +0200 Subject: [PATCH] 00189: Instead of bundled wheels, use our RPM packaged wheels @@ -8,11 +8,11 @@ We keep them in /usr/share/python-wheels Downstream only: upstream bundles We might eventually pursuit upstream support, but it's low prio --- - Lib/ensurepip/__init__.py | 36 ++++++++++++++++++++++++++---------- - 1 file changed, 26 insertions(+), 10 deletions(-) + Lib/ensurepip/__init__.py | 32 ++++++++++++++++++++++---------- + 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py -index b291e9a..798d0f4 100644 +index 9415fd73b8..f58dab1800 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -1,6 +1,7 @@ @@ -24,17 +24,16 @@ index b291e9a..798d0f4 100644 import sys import runpy import tempfile -@@ -9,8 +10,26 @@ import subprocess +@@ -8,10 +9,24 @@ import tempfile __all__ = ["version", "bootstrap"] - _PACKAGE_NAMES = ('setuptools', 'pip') --_SETUPTOOLS_VERSION = "56.0.0" --_PIP_VERSION = "23.0.1" -+ + +_WHEEL_DIR = "/usr/share/python38-wheels/" -+ + +-_SETUPTOOLS_VERSION = "49.2.1" +_wheels = {} -+ + +-_PIP_VERSION = "20.2.1" +def _get_most_recent_wheel_version(pkg): + prefix = os.path.join(_WHEEL_DIR, "{}-".format(pkg)) + _wheels[pkg] = {} @@ -49,11 +48,10 @@ index b291e9a..798d0f4 100644 +_SETUPTOOLS_VERSION = _get_most_recent_wheel_version("setuptools") + +_PIP_VERSION = _get_most_recent_wheel_version("pip") -+ + _PROJECTS = [ ("setuptools", _SETUPTOOLS_VERSION, "py3"), - ("pip", _PIP_VERSION, "py3"), -@@ -99,13 +118,10 @@ def _bootstrap(*, root=None, upgrade=False, user=False, +@@ -105,13 +120,10 @@ def _bootstrap(*, root=None, upgrade=False, user=False, # additional paths that need added to sys.path additional_paths = [] for project, version, py_tag in _PROJECTS: @@ -71,6 +69,3 @@ index b291e9a..798d0f4 100644 additional_paths.append(os.path.join(tmpdir, wheel_name)) --- -2.35.3 - diff --git a/SOURCES/00329-fips.patch b/SOURCES/00329-fips.patch index 590bda6..1c12d5d 100644 --- a/SOURCES/00329-fips.patch +++ b/SOURCES/00329-fips.patch @@ -1,4 +1,4 @@ -From 31ae5d3189a0b8ec07c55df3785d27d769bc90a5 Mon Sep 17 00:00:00 2001 +From 7b70e87ecc1a75f005bdffd644ceca6c9e9679fa Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 16:19:52 +0200 Subject: [PATCH 01/36] Expose OpenSSL FIPS_mode() as hashlib.get_fips_mode() @@ -26,12 +26,12 @@ index 56873b7..63ae836 100644 for __func_name in __always_supported: # try them all, some may not work due to the OpenSSL diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 93bf25f..2409522 100644 +index edadbcb..9874b06 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c -@@ -33,6 +33,9 @@ +@@ -26,6 +26,9 @@ #include - #include + #include "openssl/err.h" +/* Expose FIPS_mode */ +#include @@ -39,7 +39,7 @@ index 93bf25f..2409522 100644 #ifndef OPENSSL_THREADS # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" #endif -@@ -1079,12 +1082,46 @@ generate_hash_name_list(void) +@@ -1072,12 +1075,46 @@ generate_hash_name_list(void) return state.set; } @@ -123,10 +123,10 @@ index 9aaea47..30fd8a9 100644 -/*[clinic end generated code: output=38c2637f67e9bb79 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5467006d93e7479e input=a9049054013a1b77]*/ -- -2.38.1 +2.25.4 -From 9e12b2fdecca4fba5d777923f7742fffb7b6240d Mon Sep 17 00:00:00 2001 +From 4e1fa0339c257987984caa278516d46c35463385 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 25 Jul 2019 17:04:06 +0200 Subject: [PATCH 02/36] Use python's fall backs for the crypto it implements @@ -410,10 +410,10 @@ index 63ae836..1bcfdf9 100644 +if not get_fips_mode(): + del __py_new diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index e6cec4e..f40cc83 100644 +index 8b53d23..e9abcbb 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py -@@ -954,6 +954,7 @@ class KDFTests(unittest.TestCase): +@@ -945,6 +945,7 @@ class KDFTests(unittest.TestCase): iterations=1, dklen=None) self.assertEqual(out, self.pbkdf2_results['sha1'][0][0]) @@ -422,10 +422,10 @@ index e6cec4e..f40cc83 100644 self._test_pbkdf2_hmac(py_hashlib.pbkdf2_hmac) -- -2.38.1 +2.25.4 -From a7711c418ea72f9ea18bbb70a2d52ab44489066b Mon Sep 17 00:00:00 2001 +From 91b5c97d586a98cb95e215ecd2c02b18c8783e7a Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 17:19:06 +0200 Subject: [PATCH 03/36] Disable Python's hash implementations in FIPS mode, @@ -438,8 +438,8 @@ Subject: [PATCH 03/36] Disable Python's hash implementations in FIPS mode, Modules/_blake2/blake2s_impl.c | 5 +++ Modules/_hashopenssl.c | 37 +------------------ Modules/_sha3/sha3module.c | 5 +++ - setup.py | 48 +++++++++++++------------ - 7 files changed, 111 insertions(+), 58 deletions(-) + setup.py | 47 ++++++++++++------------ + 7 files changed, 110 insertions(+), 58 deletions(-) create mode 100644 Include/_hashopenssl.h diff --git a/Include/_hashopenssl.h b/Include/_hashopenssl.h @@ -596,10 +596,10 @@ index ef2f7e1..389711a 100644 if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 2409522..a51c502 100644 +index 9874b06..d733a39 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c -@@ -24,6 +24,7 @@ +@@ -17,6 +17,7 @@ #include "structmember.h" #include "hashlib.h" #include "pystrhex.h" @@ -607,18 +607,18 @@ index 2409522..a51c502 100644 /* EVP is the preferred interface to hashing in OpenSSL */ -@@ -31,10 +32,6 @@ +@@ -24,10 +25,6 @@ #include /* We use the object interface to discover what hashes OpenSSL supports. */ #include --#include +-#include "openssl/err.h" - -/* Expose FIPS_mode */ -#include #ifndef OPENSSL_THREADS # error "OPENSSL_THREADS is not defined, Python requires thread-safe OpenSSL" -@@ -76,38 +73,6 @@ class _hashlib.HASH "EVPobject *" "&EVPtype" +@@ -69,38 +66,6 @@ class _hashlib.HASH "EVPobject *" "&EVPtype" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a881a5092eecad28]*/ @@ -695,10 +695,10 @@ index c1fb618..34d09b4 100644 return NULL; } diff --git a/setup.py b/setup.py -index 0b24dd6..f7c4be1 100644 +index 84f7300..06d1ce6 100644 --- a/setup.py +++ b/setup.py -@@ -1677,7 +1677,6 @@ class PyBuildExt(build_ext): +@@ -1688,7 +1688,6 @@ class PyBuildExt(build_ext): def detect_modules(self): self.configure_compiler() self.init_inc_lib_dirs() @@ -706,7 +706,7 @@ index 0b24dd6..f7c4be1 100644 self.detect_simple_extensions() if TEST_EXTENSIONS: self.detect_test_extensions() -@@ -2165,7 +2164,7 @@ class PyBuildExt(build_ext): +@@ -2187,7 +2186,7 @@ class PyBuildExt(build_ext): sources=sources, depends=depends)) @@ -715,7 +715,7 @@ index 0b24dd6..f7c4be1 100644 # Detect SSL support for the socket module (via _ssl) config_vars = sysconfig.get_config_vars() -@@ -2186,7 +2185,7 @@ class PyBuildExt(build_ext): +@@ -2208,7 +2207,7 @@ class PyBuildExt(build_ext): if not openssl_libs: # libssl and libcrypto not found self.missing.extend(['_ssl', '_hashlib']) @@ -724,7 +724,7 @@ index 0b24dd6..f7c4be1 100644 # Find OpenSSL includes ssl_incs = find_file( -@@ -2194,7 +2193,7 @@ class PyBuildExt(build_ext): +@@ -2216,7 +2215,7 @@ class PyBuildExt(build_ext): ) if ssl_incs is None: self.missing.extend(['_ssl', '_hashlib']) @@ -733,7 +733,7 @@ index 0b24dd6..f7c4be1 100644 # OpenSSL 1.0.2 uses Kerberos for KRB5 ciphers krb5_h = find_file( -@@ -2204,12 +2203,24 @@ class PyBuildExt(build_ext): +@@ -2226,12 +2225,23 @@ class PyBuildExt(build_ext): if krb5_h: ssl_incs.extend(krb5_h) @@ -749,7 +749,6 @@ index 0b24dd6..f7c4be1 100644 + def detect_openssl_hashlib(self): + + config_vars = sysconfig.get_config_vars() -+ + if config_vars.get("HAVE_X509_VERIFY_PARAM_SET1_HOST"): self.add(Extension( @@ -758,10 +757,10 @@ index 0b24dd6..f7c4be1 100644 - library_dirs=openssl_libdirs, - libraries=openssl_libs, + **self.detect_openssl_args(), - depends=[ - 'socketmodule.h', - '_ssl/debughelpers.c', -@@ -2222,22 +2233,12 @@ class PyBuildExt(build_ext): + depends=['socketmodule.h', '_ssl/debughelpers.c']) + ) + else: +@@ -2239,22 +2249,12 @@ class PyBuildExt(build_ext): self.add(Extension('_hashlib', ['_hashopenssl.c'], depends=['hashlib.h'], @@ -788,7 +787,7 @@ index 0b24dd6..f7c4be1 100644 blake2_deps = glob(os.path.join(escape(self.srcdir), 'Modules/_blake2/impl/*')) -@@ -2247,6 +2248,7 @@ class PyBuildExt(build_ext): +@@ -2264,6 +2264,7 @@ class PyBuildExt(build_ext): ['_blake2/blake2module.c', '_blake2/blake2b_impl.c', '_blake2/blake2s_impl.c'], @@ -796,7 +795,7 @@ index 0b24dd6..f7c4be1 100644 depends=blake2_deps)) sha3_deps = glob(os.path.join(escape(self.srcdir), -@@ -2254,7 +2256,9 @@ class PyBuildExt(build_ext): +@@ -2271,7 +2272,9 @@ class PyBuildExt(build_ext): sha3_deps.append('hashlib.h') self.add(Extension('_sha3', ['_sha3/sha3module.c'], @@ -808,10 +807,10 @@ index 0b24dd6..f7c4be1 100644 def detect_nis(self): if MS_WINDOWS or CYGWIN or HOST_PLATFORM == 'qnx6': -- -2.38.1 +2.25.4 -From 5928affee1e8306877918efc417090512faea14d Mon Sep 17 00:00:00 2001 +From d9b8f21a1b5feb177ece4c595ce8b639f02548c8 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 12 Dec 2019 16:58:31 +0100 Subject: [PATCH 04/36] Expose all hashes available to OpenSSL @@ -822,10 +821,10 @@ Subject: [PATCH 04/36] Expose all hashes available to OpenSSL 2 files changed, 447 insertions(+), 1 deletion(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index a51c502..713e15a 100644 +index d733a39..6982268 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c -@@ -201,6 +201,12 @@ py_digest_by_name(const char *name) +@@ -194,6 +194,12 @@ py_digest_by_name(const char *name) else if (!strcmp(name, "blake2b512")) { digest = EVP_blake2b512(); } @@ -838,7 +837,7 @@ index a51c502..713e15a 100644 #endif } -@@ -719,6 +725,142 @@ _hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj) +@@ -712,6 +718,142 @@ _hashlib_openssl_sha512_impl(PyObject *module, PyObject *data_obj) return EVP_fast_new(module, data_obj, EVP_sha512()); } @@ -981,7 +980,7 @@ index a51c502..713e15a 100644 /*[clinic input] _hashlib.pbkdf2_hmac as pbkdf2_hmac -@@ -1094,6 +1236,14 @@ static struct PyMethodDef EVP_functions[] = { +@@ -1087,6 +1229,14 @@ static struct PyMethodDef EVP_functions[] = { _HASHLIB_OPENSSL_SHA256_METHODDEF _HASHLIB_OPENSSL_SHA384_METHODDEF _HASHLIB_OPENSSL_SHA512_METHODDEF @@ -1310,10 +1309,10 @@ index 30fd8a9..e96a752 100644 -/*[clinic end generated code: output=5467006d93e7479e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=be8e21a10dff71e7 input=a9049054013a1b77]*/ -- -2.38.1 +2.25.4 -From eb264b74a2a6fc820813edbfa611b782edcda088 Mon Sep 17 00:00:00 2001 +From d4c78750ffb431fe34a18aab7cdf84d3a68d7fc1 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 25 Jul 2019 18:13:45 +0200 Subject: [PATCH 05/36] Fix tests @@ -1323,7 +1322,7 @@ Subject: [PATCH 05/36] Fix tests 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index f40cc83..972eda1 100644 +index e9abcbb..2a55fd4 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -190,7 +190,9 @@ class HashLibTestCase(unittest.TestCase): @@ -1442,10 +1441,10 @@ index f40cc83..972eda1 100644 @requires_sha3 def test_extra_sha3(self): -- -2.38.1 +2.25.4 -From 7c34172f398cdea804e8a4671f996e9b3706ec7d Mon Sep 17 00:00:00 2001 +From 4ec7034d73e681041758fc80f75e061c0e506449 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 26 Jul 2019 11:27:57 +0200 Subject: [PATCH 06/36] Change FIPS exceptions from _blake2, _sha3 module init @@ -1584,10 +1583,10 @@ index 34d09b4..3079e1e 100644 if ((m = PyModule_Create(&_SHA3module)) == NULL) { return NULL; -- -2.38.1 +2.25.4 -From c968e85d077123510f8b6441b169b46f6e0e9d26 Mon Sep 17 00:00:00 2001 +From ed6f93218c2190d34ee0b0f4c7599d306708449f Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 26 Jul 2019 11:24:09 +0200 Subject: [PATCH 07/36] Make hashlib importable under FIPS mode @@ -1619,10 +1618,10 @@ index 1bcfdf9..898e6dc 100644 -- -2.38.1 +2.25.4 -From ea2a87a494c36eae2cc2cf343074ff0214e37517 Mon Sep 17 00:00:00 2001 +From 66c5862bb09586168caac4d6ba6142ed3198fe1d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 26 Jul 2019 15:41:10 +0200 Subject: [PATCH 08/36] Implement hmac.new using new built-in module, @@ -2250,10 +2249,10 @@ index 0000000..b472a6e +} +/*[clinic end generated code: output=10b6e8cac6d7a2c9 input=a9049054013a1b77]*/ diff --git a/setup.py b/setup.py -index f7c4be1..6fc7e72 100644 +index 06d1ce6..ca8bc2b 100644 --- a/setup.py +++ b/setup.py -@@ -2235,6 +2235,10 @@ class PyBuildExt(build_ext): +@@ -2251,6 +2251,10 @@ class PyBuildExt(build_ext): depends=['hashlib.h'], **self.detect_openssl_args()) ) @@ -2265,10 +2264,10 @@ index f7c4be1..6fc7e72 100644 # RHEL: Always force OpenSSL for md5, sha1, sha256, sha512; # don't build Python's implementations. -- -2.38.1 +2.25.4 -From 03ac0fc03e418f73ed76b203f779a083312aaff9 Mon Sep 17 00:00:00 2001 +From 6ec3a1afd87a3aa411a19727e212ebf81fee49cc Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Mon, 29 Jul 2019 12:45:11 +0200 Subject: [PATCH 09/36] FIPS review @@ -2480,10 +2479,10 @@ index ca95d72..216ed04 100644 + return PyModuleDef_Init(&_hmacopenssl_def); } -- -2.38.1 +2.25.4 -From f130424124b4cbd4b61f1dd84b69f1f4f9e766f6 Mon Sep 17 00:00:00 2001 +From 8645a4cf6ee2ad10fac3d081da78eabb06099a9c Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Mon, 29 Jul 2019 13:05:04 +0200 Subject: [PATCH 10/36] revert cosmetic nitpick and remove trailing whitespace @@ -2529,10 +2528,10 @@ index 216ed04..221714c 100644 .m_methods = hmacopenssl_functions, .m_slots = hmacopenssl_slots, -- -2.38.1 +2.25.4 -From 5259a4c7bd3d1ce2f0bdbcd0c95583c95d7d0d23 Mon Sep 17 00:00:00 2001 +From d80ae6ac0abf1e0ca5a32ff80343e927587cf5a6 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Wed, 31 Jul 2019 15:43:43 +0200 Subject: [PATCH 11/36] Add initial tests for various hashes under FIPS mode @@ -2613,10 +2612,10 @@ index 0000000..bee911e +if __name__ == "__main__": + unittest.main() -- -2.38.1 +2.25.4 -From c2b7ebc17d79f8c91572a790d425f9106d4dd70e Mon Sep 17 00:00:00 2001 +From 414c04713ad89bdeeb7a074f953c0085d541eae6 Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Thu, 1 Aug 2019 16:39:37 +0200 Subject: [PATCH 12/36] Initialize HMAC type. @@ -2682,10 +2681,10 @@ index 221714c..239445a 100644 fail: -- -2.38.1 +2.25.4 -From 931784f1a431538486905ef1d3958dfefd5478e6 Mon Sep 17 00:00:00 2001 +From 0157b52ac7f15610526497f9188eb84ed3846993 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 1 Aug 2019 17:57:05 +0200 Subject: [PATCH 13/36] Use a stronger hash in multiprocessing handshake @@ -2730,10 +2729,10 @@ index 8e2facf..bb4acb6 100644 response = connection.recv_bytes(256) # reject large message if response != WELCOME: -- -2.38.1 +2.25.4 -From 8a68ba81a66181d9a4b6c7b1e77f944efada2aae Mon Sep 17 00:00:00 2001 +From 3730b4186cf708bb8ea528c22734d4c1176fc9ad Mon Sep 17 00:00:00 2001 From: Marcel Plch Date: Fri, 2 Aug 2019 17:36:01 +0200 Subject: [PATCH 14/36] Fix refcounting @@ -2804,10 +2803,10 @@ index 239445a..9c28828 100644 -- -2.38.1 +2.25.4 -From 5d835c236b392e8741fabe9b9d83d5482842dd87 Mon Sep 17 00:00:00 2001 +From 1873bfe385a1b952ba11c2b2f15755353f2411df Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 13:37:05 +0200 Subject: [PATCH 15/36] hmac: Don't default to md5 in FIPS mode @@ -2830,10 +2829,10 @@ index daabc8c..0302364 100644 result = _hmacopenssl.new(key, digestmod=name) if msg: -- -2.38.1 +2.25.4 -From d865fb5a73ffaf39de68b69c9ccb81ca17b6c430 Mon Sep 17 00:00:00 2001 +From f77c854b9c5aab3e2bb517b6d0c08197a116efb1 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 14:20:58 +0200 Subject: [PATCH 16/36] Make _hmacopenssl.HMAC subclassable; subclass it as @@ -3121,10 +3120,10 @@ index b472a6e..861acc1 100644 -/*[clinic end generated code: output=10b6e8cac6d7a2c9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d93ad460795d49b5 input=a9049054013a1b77]*/ -- -2.38.1 +2.25.4 -From 0a75e9886721aa076542a40159b02fbd18bd8cd3 Mon Sep 17 00:00:00 2001 +From b357a1f823b7b231d1a8bc149b5a950246350d3c Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 16:10:36 +0200 Subject: [PATCH 17/36] Fix _hmacopenssl.HMAC.block_size @@ -3147,10 +3146,10 @@ index 7d3d973..a24c8ba 100644 static PyMethodDef Hmac_methods[] = { -- -2.38.1 +2.25.4 -From 68b4ee700ed23422472c9b96cf0631cb5a5dab6e Mon Sep 17 00:00:00 2001 +From ee03c8ff14206070a7e4e4d13c4b067bcf25193d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 15:02:08 +0200 Subject: [PATCH 18/36] distutils upload: Skip md5 checksum in FIPS mode @@ -3229,10 +3228,10 @@ index c17d8e7..b4b64e9 100644 def test_upload_fails(self): -- -2.38.1 +2.25.4 -From 62c8250c2996af8e4d112676c0995616583fafa7 Mon Sep 17 00:00:00 2001 +From fd0fd3310ff7c7dae0ea4377b71928ca3e242a21 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 15:32:25 +0200 Subject: [PATCH 19/36] Fix HMAC tests on FIPS mode @@ -3322,10 +3321,10 @@ index 23c108f..0a85981 100644 def test_equality(self): # Testing if the copy has the same digests. -- -2.38.1 +2.25.4 -From a7f5d3a4712694e6b74295ba6980c554b56d7227 Mon Sep 17 00:00:00 2001 +From e0c4dfcfc3070d0b3b25f77357509b9daa5f9891 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 16:37:12 +0200 Subject: [PATCH 20/36] test_tools: Skip md5sum tests in FIPS mode @@ -3355,10 +3354,10 @@ index fb565b7..7028a4d 100644 @classmethod def setUpClass(cls): -- -2.38.1 +2.25.4 -From 9e6cfe34f7377761f758d57a1b68a62fd4d0f2d1 Mon Sep 17 00:00:00 2001 +From 510915020bb7c7c91d297fb3330ee9be3ee16b6f Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 18:23:57 +0200 Subject: [PATCH 21/36] Make hashlib tests pass in FIPS mode @@ -3368,7 +3367,7 @@ Subject: [PATCH 21/36] Make hashlib tests pass in FIPS mode 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index 972eda1..19a9868 100644 +index 2a55fd4..9ae5efc 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -28,6 +28,11 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') @@ -3528,7 +3527,7 @@ index 972eda1..19a9868 100644 @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems') @bigmemtest(size=_4G - 1, memuse=1, dry_run=False) def test_case_md5_uintmax(self, size): -@@ -851,14 +878,16 @@ class HashLibTestCase(unittest.TestCase): +@@ -842,14 +869,16 @@ class HashLibTestCase(unittest.TestCase): m = cons(b'x' * gil_minsize) m.update(b'1') @@ -3550,10 +3549,10 @@ index 972eda1..19a9868 100644 @support.reap_threads def test_threaded_hashing(self): -- -2.38.1 +2.25.4 -From 22b6dcc045d87d130852bc4f017cfb6305b329dd Mon Sep 17 00:00:00 2001 +From de9997db1f55fe4c70f0a5c4fe5b497e8c6839a2 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 14 Aug 2019 14:43:07 +0200 Subject: [PATCH 22/36] distutils upload: only add md5 if available, but @@ -3620,10 +3619,10 @@ index b4b64e9..f720a79 100644 def test_upload_fails(self): -- -2.38.1 +2.25.4 -From b02daa9dbf4fcd2d1e067d63873d276bd7bf132f Mon Sep 17 00:00:00 2001 +From 30407ef6fd2fb0fcb950cab57d4bd23121ef9084 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Fri, 13 Sep 2019 02:30:00 +0200 Subject: [PATCH 23/36] bpo-9216: Add usedforsecurity to hashlib constructors @@ -3657,7 +3656,7 @@ Contributed and Signed-off-by: Christian Heimes christian@python.org create mode 100644 Misc/NEWS.d/next/Library/2019-09-12-14-54-45.bpo-9216.W7QMpC.rst diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst -index f5da6ec..86b9f65 100644 +index a16c7cd..6eb3a7b 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -67,7 +67,7 @@ Constructors for hash algorithms that are always present in this module are @@ -3709,7 +3708,7 @@ index f5da6ec..86b9f65 100644 These functions return the corresponding hash objects for calculating diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index 19a9868..3ee9b14 100644 +index 9ae5efc..08bb91f 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -226,6 +226,15 @@ class HashLibTestCase(unittest.TestCase): @@ -3945,10 +3944,10 @@ index 560bd68..71c5706 100644 -/*[clinic end generated code: output=39af5a74c8805b36 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c80d8d06ce40a192 input=a9049054013a1b77]*/ diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index 713e15a..b4d05ab 100644 +index 6982268..a1f81eb 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c -@@ -528,7 +528,7 @@ static PyTypeObject EVPtype = { +@@ -521,7 +521,7 @@ static PyTypeObject EVPtype = { \ static PyObject * EVPnew(const EVP_MD *digest, @@ -3957,7 +3956,7 @@ index 713e15a..b4d05ab 100644 { int result = 0; EVPobject *self; -@@ -541,6 +541,12 @@ EVPnew(const EVP_MD *digest, +@@ -534,6 +534,12 @@ EVPnew(const EVP_MD *digest, if ((self = newEVPobject()) == NULL) return NULL; @@ -3970,7 +3969,7 @@ index 713e15a..b4d05ab 100644 if (!EVP_DigestInit_ex(self->ctx, digest, NULL)) { _setException(PyExc_ValueError); Py_DECREF(self); -@@ -572,6 +578,8 @@ _hashlib.new as EVP_new +@@ -565,6 +571,8 @@ _hashlib.new as EVP_new name as name_obj: object string as data_obj: object(c_default="NULL") = b'' @@ -3979,7 +3978,7 @@ index 713e15a..b4d05ab 100644 Return a new hash object using the named algorithm. -@@ -582,8 +590,9 @@ The MD5 and SHA1 algorithms are always supported. +@@ -575,8 +583,9 @@ The MD5 and SHA1 algorithms are always supported. [clinic start generated code]*/ static PyObject * @@ -3991,7 +3990,7 @@ index 713e15a..b4d05ab 100644 { Py_buffer view = { 0 }; PyObject *ret_obj; -@@ -600,7 +609,9 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj) +@@ -593,7 +602,9 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj) digest = py_digest_by_name(name); @@ -4002,7 +4001,7 @@ index 713e15a..b4d05ab 100644 if (data_obj) PyBuffer_Release(&view); -@@ -608,7 +619,8 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj) +@@ -601,7 +612,8 @@ EVP_new_impl(PyObject *module, PyObject *name_obj, PyObject *data_obj) } static PyObject* @@ -4012,7 +4011,7 @@ index 713e15a..b4d05ab 100644 { Py_buffer view = { 0 }; PyObject *ret_obj; -@@ -616,7 +628,8 @@ EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest) +@@ -609,7 +621,8 @@ EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest) if (data_obj) GET_BUFFER_VIEW_OR_ERROUT(data_obj, &view); @@ -4022,7 +4021,7 @@ index 713e15a..b4d05ab 100644 if (data_obj) PyBuffer_Release(&view); -@@ -628,16 +641,19 @@ EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest) +@@ -621,16 +634,19 @@ EVP_fast_new(PyObject *module, PyObject *data_obj, const EVP_MD *digest) _hashlib.openssl_md5 string as data_obj: object(py_default="b''") = NULL @@ -4045,7 +4044,7 @@ index 713e15a..b4d05ab 100644 } -@@ -645,16 +661,19 @@ _hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj) +@@ -638,16 +654,19 @@ _hashlib_openssl_md5_impl(PyObject *module, PyObject *data_obj) _hashlib.openssl_sha1 string as data_obj: object(py_default="b''") = NULL @@ -4068,7 +4067,7 @@ index 713e15a..b4d05ab 100644 } -@@ -662,16 +681,19 @@ _hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj) +@@ -655,16 +674,19 @@ _hashlib_openssl_sha1_impl(PyObject *module, PyObject *data_obj) _hashlib.openssl_sha224 string as data_obj: object(py_default="b''") = NULL @@ -4091,7 +4090,7 @@ index 713e15a..b4d05ab 100644 } -@@ -679,16 +701,19 @@ _hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj) +@@ -672,16 +694,19 @@ _hashlib_openssl_sha224_impl(PyObject *module, PyObject *data_obj) _hashlib.openssl_sha256 string as data_obj: object(py_default="b''") = NULL @@ -4114,7 +4113,7 @@ index 713e15a..b4d05ab 100644 } -@@ -696,16 +721,19 @@ _hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj) +@@ -689,16 +714,19 @@ _hashlib_openssl_sha256_impl(PyObject *module, PyObject *data_obj) _hashlib.openssl_sha384 string as data_obj: object(py_default="b''") = NULL @@ -4137,7 +4136,7 @@ index 713e15a..b4d05ab 100644 } -@@ -713,152 +741,179 @@ _hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj) +@@ -706,152 +734,179 @@ _hashlib_openssl_sha384_impl(PyObject *module, PyObject *data_obj) _hashlib.openssl_sha512 string as data_obj: object(py_default="b''") = NULL @@ -5730,7 +5729,7 @@ index 459a934..b8185b6 100644 -/*[clinic end generated code: output=580df4b667084a7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bbfa72d8703c82b5 input=a9049054013a1b77]*/ diff --git a/Modules/md5module.c b/Modules/md5module.c -index 64fab80..ee4efe4 100644 +index c2ebaaf..fdc4d7b 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -503,13 +503,15 @@ static PyTypeObject MD5type = { @@ -5752,7 +5751,7 @@ index 64fab80..ee4efe4 100644 MD5object *new; Py_buffer buf; diff --git a/Modules/sha1module.c b/Modules/sha1module.c -index 4a8dbd8..aec0bad 100644 +index ce2ad26..4d191c3 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -480,13 +480,15 @@ static PyTypeObject SHA1type = { @@ -5774,7 +5773,7 @@ index 4a8dbd8..aec0bad 100644 SHA1object *new; Py_buffer buf; diff --git a/Modules/sha256module.c b/Modules/sha256module.c -index a1c8b1a..8777c59 100644 +index b8d6c4c..245f4c0 100644 --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -601,13 +601,15 @@ static PyTypeObject SHA256type = { @@ -5814,7 +5813,7 @@ index a1c8b1a..8777c59 100644 SHAobject *new; Py_buffer buf; diff --git a/Modules/sha512module.c b/Modules/sha512module.c -index 4167fd3..504d40a 100644 +index 98b9791..df4f9d2 100644 --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -666,13 +666,15 @@ static PyTypeObject SHA512type = { @@ -5854,10 +5853,10 @@ index 4167fd3..504d40a 100644 SHAobject *new; Py_buffer buf; -- -2.38.1 +2.25.4 -From 0ee86826a425528d1f129788ad3e9e144e81da83 Mon Sep 17 00:00:00 2001 +From 095d8ea318b20b5d42ada0367ca770c15e6f6fa2 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 26 Aug 2019 19:09:39 +0200 Subject: [PATCH 24/36] Test the usedforsecurity flag @@ -5867,7 +5866,7 @@ Subject: [PATCH 24/36] Test the usedforsecurity flag 1 file changed, 54 insertions(+), 34 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index 3ee9b14..a991f0a 100644 +index 08bb91f..1368e91 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -21,6 +21,7 @@ from test import support @@ -6080,9 +6079,9 @@ index 3ee9b14..a991f0a 100644 - self.check('md5', b'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3') + self.check('md5', b'A'*size, '28138d306ff1b8281f1a9067e1a1a2b3', usedforsecurity=False) - @unittest.skipIf(sys.maxsize < _4G - 1, 'test cannot run on 32-bit systems') - @bigmemtest(size=_4G - 1, memuse=1, dry_run=False) -@@ -934,6 +944,16 @@ class HashLibTestCase(unittest.TestCase): + # use the three examples from Federal Information Processing Standards + # Publication 180-1, Secure Hash Standard, 1995 April 17 +@@ -925,6 +935,16 @@ class HashLibTestCase(unittest.TestCase): self.assertEqual(expected_hash, hasher.hexdigest()) @@ -6100,10 +6099,10 @@ index 3ee9b14..a991f0a 100644 class KDFTests(unittest.TestCase): -- -2.38.1 +2.25.4 -From 7602d70630fa0e736ad518b243079b658893d653 Mon Sep 17 00:00:00 2001 +From 59b7e853d919380ca6c11655bbc7041ee395417d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 29 Aug 2019 10:25:28 +0200 Subject: [PATCH 25/36] Skip error checking in _hashlib.get_fips_mode @@ -6114,10 +6113,10 @@ Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1745499 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c -index b4d05ab..a48b607 100644 +index a1f81eb..eff331b 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c -@@ -1260,20 +1260,22 @@ _hashlib_get_fips_mode_impl(PyObject *module) +@@ -1253,20 +1253,22 @@ _hashlib_get_fips_mode_impl(PyObject *module) /*[clinic end generated code: output=ad8a7793310d3f98 input=f42a2135df2a5e11]*/ { @@ -6155,10 +6154,10 @@ index b4d05ab..a48b607 100644 -- -2.38.1 +2.25.4 -From 07552e7758fdc9c9610d773b4100d4686b5353a3 Mon Sep 17 00:00:00 2001 +From 7f5432d72546f60078989b6cadf26cd51de84ebd Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 10 Oct 2019 13:04:50 +0200 Subject: [PATCH 26/36] Skip error checking in _Py_hashlib_fips_error @@ -6193,10 +6192,10 @@ index 47ed003..d4cbdef 100644 } PyErr_Format(exc, "%s is not available in FIPS mode", name); -- -2.38.1 +2.25.4 -From 8be15a9faf79a062be4b0f27605737bc34687e68 Mon Sep 17 00:00:00 2001 +From 05f7188136bda8eeec06428aa4ddf9ab14a178a0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 5 Aug 2019 19:12:38 +0200 Subject: [PATCH 27/36] Fixups @@ -6235,10 +6234,10 @@ index 0a85981..0b481ec 100644 h1 = hmac.HMAC(b"key", digestmod="sha1") h2 = h1.copy() -- -2.38.1 +2.25.4 -From 112646fbf2af81df1750140f7486b32296518099 Mon Sep 17 00:00:00 2001 +From 0f707443431d9dc22218be7208d940f4d42f122d Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 26 Aug 2019 19:39:48 +0200 Subject: [PATCH 28/36] Don't re-export get_fips_mode from hashlib @@ -6446,7 +6445,7 @@ index 34812e6..86e61e2 100644 self.compare_hashes(hashlib.shake_128(b'abc'), _hashlib.openssl_shake_128(b'abc')) self.compare_hashes(hashlib.shake_256(b'abc'), _hashlib.openssl_shake_256(b'abc')) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index a991f0a..b535059 100644 +index 1368e91..a4b7840 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -29,7 +29,9 @@ COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount') @@ -6502,7 +6501,7 @@ index a991f0a..b535059 100644 self.check_blocksize_name('md5', 64, 16) self.check_blocksize_name('sha1', 64, 20) self.check_blocksize_name('sha224', 64, 28) -@@ -944,7 +946,7 @@ class HashLibTestCase(unittest.TestCase): +@@ -935,7 +937,7 @@ class HashLibTestCase(unittest.TestCase): self.assertEqual(expected_hash, hasher.hexdigest()) @@ -6551,7 +6550,7 @@ index 0b481ec..cc77928 100644 def test_realcopy(self): # Testing if the copy method created a real copy. diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py -index d14eb45..af53ec9 100644 +index d0c9862..9a44c0d 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -17,6 +17,8 @@ import select @@ -6563,7 +6562,7 @@ index d14eb45..af53ec9 100644 import unittest from test import support, mock_socket -@@ -1114,7 +1116,7 @@ class SMTPSimTests(unittest.TestCase): +@@ -1021,7 +1023,7 @@ class SMTPSimTests(unittest.TestCase): def testAUTH_multiple(self): # Test that multiple authentication methods are tried. @@ -6605,10 +6604,10 @@ index 1cb358f..6f5cb7f 100644 from test import support -- -2.38.1 +2.25.4 -From 69a0ddba408a9595aa0fc5b3fdfe7e59838acea2 Mon Sep 17 00:00:00 2001 +From 9515f9be3409fdc59cf9c09dd200917483e1651a Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Wed, 20 Nov 2019 10:59:25 +0100 Subject: [PATCH 29/36] Use FIPS compliant CSPRNG @@ -6625,7 +6624,7 @@ Signed-off-by: Christian Heimes 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py -index 5302b1c..ed335ad 100644 +index 2a4ae15..5ad5bd6 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1546,6 +1546,11 @@ class GetRandomTests(unittest.TestCase): @@ -6641,7 +6640,7 @@ index 5302b1c..ed335ad 100644 def test_getrandom_type(self): data = os.getrandom(16) diff --git a/Makefile.pre.in b/Makefile.pre.in -index 381a8ab..e7778f4 100644 +index 917303d..ddfbfd0 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -116,7 +116,7 @@ PY_STDMODULE_CFLAGS= $(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFOR @@ -6654,10 +6653,10 @@ index 381a8ab..e7778f4 100644 CFLAGS_ALIASING=@CFLAGS_ALIASING@ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c -index d7edabe..f825d5a 100644 +index 726e372..9a1249a 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c -@@ -389,6 +389,9 @@ extern char *ctermid_r(char *); +@@ -388,6 +388,9 @@ extern char *ctermid_r(char *); #define MODNAME "posix" #endif @@ -6667,7 +6666,7 @@ index d7edabe..f825d5a 100644 #if defined(__sun) /* Something to implement in autoconf, not present in autoconf 2.69 */ #define HAVE_STRUCT_STAT_ST_FSTYPE 1 -@@ -13650,6 +13653,11 @@ os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) +@@ -13558,6 +13561,11 @@ os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags) return posix_error(); } @@ -6773,10 +6772,10 @@ index eb2b6d0..cb38cfe 100644 return win32_urandom((unsigned char *)buffer, size, raise); #else -- -2.38.1 +2.25.4 -From 72894033d2c1d29897204c5272d8f2878c17254c Mon Sep 17 00:00:00 2001 +From ba95383d9b37f252bd153674404dc4055d49bf82 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 28 Nov 2019 17:26:02 +0100 Subject: [PATCH 30/36] Fixups for FIPS compliant CSPRNG @@ -6787,7 +6786,7 @@ Subject: [PATCH 30/36] Fixups for FIPS compliant CSPRNG 2 files changed, 5 insertions(+), 31 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py -index ed335ad..f306316 100644 +index 5ad5bd6..ae53de9 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -28,6 +28,7 @@ import time @@ -6872,10 +6871,10 @@ index cb38cfe..08fa29a 100644 return 0; } -- -2.38.1 +2.25.4 -From d8bc6ab755acf0e2feffda802aeed032a2319df8 Mon Sep 17 00:00:00 2001 +From 496a58146aa42b97661c5ea1afeaa223e8fd4ceb Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 2 Apr 2020 16:50:37 +0200 Subject: [PATCH 31/36] Do not raise a ValueError if digestmod is missing in @@ -6902,10 +6901,10 @@ index 5055027..ee1ad76 100644 return digestmod.lower() elif callable(digestmod): -- -2.38.1 +2.25.4 -From 9dd6dc8c11b96ac74abf220ed76d1176041c3711 Mon Sep 17 00:00:00 2001 +From 3f346ea93c2504e169a2df21e2de206031a08600 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Thu, 2 Apr 2020 16:55:36 +0200 Subject: [PATCH 32/36] Regenerate the clinic files @@ -6989,10 +6988,10 @@ index 861acc1..527be83 100644 -/*[clinic end generated code: output=d93ad460795d49b5 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9b75c31e1116bf6f input=a9049054013a1b77]*/ -- -2.38.1 +2.25.4 -From f646402958e8d284519ef7f72d0225ace210ffa7 Mon Sep 17 00:00:00 2001 +From f4465980ae75c0e56cd1edecf9a42fa38b9cd12a Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 7 Apr 2020 15:16:45 +0200 Subject: [PATCH 33/36] Pass kwargs (like usedforsecurity) through __hash_new @@ -7024,10 +7023,10 @@ index 2fc214e..785858f 100644 try: -- -2.38.1 +2.25.4 -From bd206ed69e7c19b62f0174a649b5c2d03f0d9f5b Mon Sep 17 00:00:00 2001 +From 6c0ba219c01052f8b079ce67b89a75920b3aa867 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 7 Apr 2020 15:18:48 +0200 Subject: [PATCH 34/36] Adjust new upstream test for failing hashes with @@ -7038,7 +7037,7 @@ Subject: [PATCH 34/36] Adjust new upstream test for failing hashes with 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py -index b535059..6e846c4 100644 +index a4b7840..a858bf4 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -239,15 +239,23 @@ class HashLibTestCase(unittest.TestCase): @@ -7070,10 +7069,10 @@ index b535059..6e846c4 100644 self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') self.assertRaises(TypeError, hashlib.new, 1) -- -2.38.1 +2.25.4 -From d1ce20110573989382948a901896169eb637b265 Mon Sep 17 00:00:00 2001 +From 041105f888785599e58213dfea55115a4e861d77 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Fri, 24 Apr 2020 19:57:16 +0200 Subject: [PATCH 35/36] Skip the test_with_digestmod_no_default under FIPS @@ -7116,10 +7115,10 @@ index cc77928..fd068e0 100644 class ConstructorTestCase(unittest.TestCase): -- -2.38.1 +2.25.4 -From bff06e176e60200582a42611d4fe3c240da314a3 Mon Sep 17 00:00:00 2001 +From e20750200d560a549cbbf224ded74bb086ef3e66 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Tue, 31 Mar 2020 18:00:42 +0200 Subject: [PATCH 36/36] Add a sentinel value on the Hmac_members table of the @@ -7142,5 +7141,5 @@ index 9577cad..4bd7c15 100644 PyDoc_STRVAR(hmactype_doc, -- -2.38.1 +2.25.4 diff --git a/SOURCES/00357-CVE-2021-3177.patch b/SOURCES/00357-CVE-2021-3177.patch new file mode 100644 index 0000000..9f32054 --- /dev/null +++ b/SOURCES/00357-CVE-2021-3177.patch @@ -0,0 +1,186 @@ +From ece5dfd403dac211f8d3c72701fe7ba7b7aa5b5f Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Mon, 18 Jan 2021 13:28:52 -0800 +Subject: [PATCH] closes bpo-42938: Replace snprintf with Python unicode + formatting in ctypes param reprs. (GH-24248) + +(cherry picked from commit 916610ef90a0d0761f08747f7b0905541f0977c7) + +Co-authored-by: Benjamin Peterson + +Co-authored-by: Benjamin Peterson +--- + Lib/ctypes/test/test_parameters.py | 43 ++++++++++++++++ + .../2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst | 2 + + Modules/_ctypes/callproc.c | 51 +++++++------------ + 3 files changed, 64 insertions(+), 32 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst + +diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py +index e4c25fd880cef..531894fdec838 100644 +--- a/Lib/ctypes/test/test_parameters.py ++++ b/Lib/ctypes/test/test_parameters.py +@@ -201,6 +201,49 @@ def __dict__(self): + with self.assertRaises(ZeroDivisionError): + WorseStruct().__setstate__({}, b'foo') + ++ def test_parameter_repr(self): ++ from ctypes import ( ++ c_bool, ++ c_char, ++ c_wchar, ++ c_byte, ++ c_ubyte, ++ c_short, ++ c_ushort, ++ c_int, ++ c_uint, ++ c_long, ++ c_ulong, ++ c_longlong, ++ c_ulonglong, ++ c_float, ++ c_double, ++ c_longdouble, ++ c_char_p, ++ c_wchar_p, ++ c_void_p, ++ ) ++ self.assertRegex(repr(c_bool.from_param(True)), r"^$") ++ self.assertEqual(repr(c_char.from_param(97)), "") ++ self.assertRegex(repr(c_wchar.from_param('a')), r"^$") ++ self.assertEqual(repr(c_byte.from_param(98)), "") ++ self.assertEqual(repr(c_ubyte.from_param(98)), "") ++ self.assertEqual(repr(c_short.from_param(511)), "") ++ self.assertEqual(repr(c_ushort.from_param(511)), "") ++ self.assertRegex(repr(c_int.from_param(20000)), r"^$") ++ self.assertRegex(repr(c_uint.from_param(20000)), r"^$") ++ self.assertRegex(repr(c_long.from_param(20000)), r"^$") ++ self.assertRegex(repr(c_ulong.from_param(20000)), r"^$") ++ self.assertRegex(repr(c_longlong.from_param(20000)), r"^$") ++ self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^$") ++ self.assertEqual(repr(c_float.from_param(1.5)), "") ++ self.assertEqual(repr(c_double.from_param(1.5)), "") ++ self.assertEqual(repr(c_double.from_param(1e300)), "") ++ self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^$") ++ self.assertRegex(repr(c_char_p.from_param(b'hihi')), "^$") ++ self.assertRegex(repr(c_wchar_p.from_param('hihi')), "^$") ++ self.assertRegex(repr(c_void_p.from_param(0x12)), r"^$") ++ + ################################################################ + + if __name__ == '__main__': +diff --git a/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst b/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst +new file mode 100644 +index 0000000000000..7df65a156feab +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst +@@ -0,0 +1,2 @@ ++Avoid static buffers when computing the repr of :class:`ctypes.c_double` and ++:class:`ctypes.c_longdouble` values. +diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c +index a9b8675cd951b..de75918d49f37 100644 +--- a/Modules/_ctypes/callproc.c ++++ b/Modules/_ctypes/callproc.c +@@ -484,58 +484,47 @@ is_literal_char(unsigned char c) + static PyObject * + PyCArg_repr(PyCArgObject *self) + { +- char buffer[256]; + switch(self->tag) { + case 'b': + case 'B': +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, self->value.b); +- break; + case 'h': + case 'H': +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, self->value.h); +- break; + case 'i': + case 'I': +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, self->value.i); +- break; + case 'l': + case 'L': +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, self->value.l); +- break; + + case 'q': + case 'Q': +- sprintf(buffer, +-#ifdef MS_WIN32 +- "", +-#else +- "", +-#endif ++ return PyUnicode_FromFormat("", + self->tag, self->value.q); +- break; + case 'd': +- sprintf(buffer, "", +- self->tag, self->value.d); +- break; +- case 'f': +- sprintf(buffer, "", +- self->tag, self->value.f); +- break; +- ++ case 'f': { ++ PyObject *f = PyFloat_FromDouble((self->tag == 'f') ? self->value.f : self->value.d); ++ if (f == NULL) { ++ return NULL; ++ } ++ PyObject *result = PyUnicode_FromFormat("", self->tag, f); ++ Py_DECREF(f); ++ return result; ++ } + case 'c': + if (is_literal_char((unsigned char)self->value.c)) { +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, self->value.c); + } + else { +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, (unsigned char)self->value.c); + } +- break; + + /* Hm, are these 'z' and 'Z' codes useful at all? + Shouldn't they be replaced by the functionality of c_string +@@ -544,22 +533,20 @@ PyCArg_repr(PyCArgObject *self) + case 'z': + case 'Z': + case 'P': +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + self->tag, self->value.p); + break; + + default: + if (is_literal_char((unsigned char)self->tag)) { +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + (unsigned char)self->tag, (void *)self); + } + else { +- sprintf(buffer, "", ++ return PyUnicode_FromFormat("", + (unsigned char)self->tag, (void *)self); + } +- break; + } +- return PyUnicode_FromString(buffer); + } + + static PyMemberDef PyCArgType_members[] = { diff --git a/SOURCES/00359-CVE-2021-23336.patch b/SOURCES/00359-CVE-2021-23336.patch deleted file mode 100644 index 33e91c2..0000000 --- a/SOURCES/00359-CVE-2021-23336.patch +++ /dev/null @@ -1,567 +0,0 @@ -From 78da9e020385fe78e36c20f99a0910bbc4a0c100 Mon Sep 17 00:00:00 2001 -From: Lumir Balhar -Date: Thu, 1 Apr 2021 08:18:07 +0200 -Subject: [PATCH] CVE-2021-23336: Add `separator` argument to parse_qs; warn - with default -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Partially backports https://bugs.python.org/issue42967 : [security] Address a web cache-poisoning issue reported in urllib.parse.parse_qsl(). -However, this solution is different than the upstream solution in Python 3.6.13. - -An optional argument seperator is added to specify the separator. -It is recommended to set it to '&' or ';' to match the application or proxy in use. -The default can be set with an env variable of a config file. -If neither the argument, env var or config file specifies a separator, "&" is used -but a warning is raised if parse_qs is used on input that contains ';'. - -Co-authors of the upstream change (who do not necessarily agree with this): -Co-authored-by: Adam Goldschmidt -Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> -Co-authored-by: Éric Araujo ---- - Doc/library/cgi.rst | 2 +- - Doc/library/urllib.parse.rst | 12 +- - Lib/cgi.py | 4 +- - Lib/test/test_cgi.py | 29 +++++ - Lib/test/test_urlparse.py | 232 ++++++++++++++++++++++++++++++++++- - Lib/urllib/parse.py | 78 +++++++++++- - 6 files changed, 339 insertions(+), 18 deletions(-) - -diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst -index 880074b..d8a6dc1 100644 ---- a/Doc/library/cgi.rst -+++ b/Doc/library/cgi.rst -@@ -277,7 +277,7 @@ These are useful if you want more control, or if you want to employ some of the - algorithms implemented in this module in other circumstances. - - --.. function:: parse(fp=None, environ=os.environ, keep_blank_values=False, strict_parsing=False, separator="&") -+.. function:: parse(fp=None, environ=os.environ, keep_blank_values=False, strict_parsing=False, separator=None) - - Parse a query in the environment or from a file (the file defaults to - ``sys.stdin``). The *keep_blank_values*, *strict_parsing* and *separator* parameters are -diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst -index a6cfc5d..85b2448 100644 ---- a/Doc/library/urllib.parse.rst -+++ b/Doc/library/urllib.parse.rst -@@ -165,7 +165,7 @@ or on combining URL components into a URL string. - now raise :exc:`ValueError`. - - --.. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&') -+.. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator=None) - - Parse a query string given as a string argument (data of type - :mimetype:`application/x-www-form-urlencoded`). Data are returned as a -@@ -191,7 +191,13 @@ or on combining URL components into a URL string. - *max_num_fields* fields read. - - The optional argument *separator* is the symbol to use for separating the -- query arguments. It defaults to ``&``. -+ query arguments. It is recommended to set it to ``'&'`` or ``';'``. -+ It defaults to ``'&'``; a warning is raised if this default is used. -+ This default may be changed with the following environment variable settings: -+ -+ - ``PYTHON_URLLIB_QS_SEPARATOR='&'``: use only ``&`` as separator, without warning (as in Python 3.6.13+ or 3.10) -+ - ``PYTHON_URLLIB_QS_SEPARATOR=';'``: use only ``;`` as separator -+ - ``PYTHON_URLLIB_QS_SEPARATOR=legacy``: use both ``&`` and ``;`` (as in previous versions of Python) - - Use the :func:`urllib.parse.urlencode` function (with the ``doseq`` - parameter set to ``True``) to convert such dictionaries into query -@@ -236,7 +242,7 @@ or on combining URL components into a URL string. - *max_num_fields* fields read. - - The optional argument *separator* is the symbol to use for separating the -- query arguments. It defaults to ``&``. -+ query arguments. It works as in :py:func:`parse_qs`. - - Use the :func:`urllib.parse.urlencode` function to convert such lists of pairs into - query strings. -diff --git a/Lib/cgi.py b/Lib/cgi.py -index 1e880e5..d7b994b 100755 ---- a/Lib/cgi.py -+++ b/Lib/cgi.py -@@ -116,7 +116,7 @@ log = initlog # The current logging function - maxlen = 0 - - def parse(fp=None, environ=os.environ, keep_blank_values=0, -- strict_parsing=0, separator='&'): -+ strict_parsing=0, separator=None): - """Parse a query in the environment or from a file (default stdin) - - Arguments, all optional: -@@ -319,7 +319,7 @@ class FieldStorage: - def __init__(self, fp=None, headers=None, outerboundary=b'', - environ=os.environ, keep_blank_values=0, strict_parsing=0, - limit=None, encoding='utf-8', errors='replace', -- max_num_fields=None, separator='&'): -+ max_num_fields=None, separator=None): - """Constructor. Read multipart/* until last part. - - Arguments, all optional: -diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py -index 4e1506a..49b6926 100644 ---- a/Lib/test/test_cgi.py -+++ b/Lib/test/test_cgi.py -@@ -180,6 +180,35 @@ Content-Length: 3 - - env = {'QUERY_STRING': orig} - fs = cgi.FieldStorage(environ=env) -+ if isinstance(expect, dict): -+ # test dict interface -+ self.assertEqual(len(expect), len(fs)) -+ self.assertCountEqual(expect.keys(), fs.keys()) -+ self.assertEqual(fs.getvalue("nonexistent field", "default"), "default") -+ # test individual fields -+ for key in expect.keys(): -+ expect_val = expect[key] -+ self.assertIn(key, fs) -+ if len(expect_val) > 1: -+ self.assertEqual(fs.getvalue(key), expect_val) -+ else: -+ self.assertEqual(fs.getvalue(key), expect_val[0]) -+ -+ def test_separator(self): -+ parse_semicolon = [ -+ ("x=1;y=2.0", {'x': ['1'], 'y': ['2.0']}), -+ ("x=1;y=2.0;z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}), -+ (";", ValueError("bad query field: ''")), -+ (";;", ValueError("bad query field: ''")), -+ ("=;a", ValueError("bad query field: 'a'")), -+ (";b=a", ValueError("bad query field: ''")), -+ ("b;=a", ValueError("bad query field: 'b'")), -+ ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}), -+ ("a=a+b;a=b+a", {'a': ['a b', 'b a']}), -+ ] -+ for orig, expect in parse_semicolon: -+ env = {'QUERY_STRING': orig} -+ fs = cgi.FieldStorage(separator=';', environ=env) - if isinstance(expect, dict): - # test dict interface - self.assertEqual(len(expect), len(fs)) -diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py -index 0f99130..4e0d7e5 100644 ---- a/Lib/test/test_urlparse.py -+++ b/Lib/test/test_urlparse.py -@@ -2,6 +2,11 @@ import sys - import unicodedata - import unittest - import urllib.parse -+from test.support import EnvironmentVarGuard -+from warnings import catch_warnings -+import tempfile -+import contextlib -+import os.path - - RFC1808_BASE = "http://a/b/c/d;p?q#f" - RFC2396_BASE = "http://a/b/c/d;p?q" -@@ -32,10 +37,34 @@ parse_qsl_test_cases = [ - (b"&a=b", [(b'a', b'b')]), - (b"a=a+b&b=b+c", [(b'a', b'a b'), (b'b', b'b c')]), - (b"a=1&a=2", [(b'a', b'1'), (b'a', b'2')]), -+] -+ -+parse_qsl_test_cases_semicolon = [ -+ (";", []), -+ (";;", []), -+ (";a=b", [('a', 'b')]), -+ ("a=a+b;b=b+c", [('a', 'a b'), ('b', 'b c')]), -+ ("a=1;a=2", [('a', '1'), ('a', '2')]), -+ (b";", []), -+ (b";;", []), -+ (b";a=b", [(b'a', b'b')]), -+ (b"a=a+b;b=b+c", [(b'a', b'a b'), (b'b', b'b c')]), -+ (b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]), -+] -+ -+parse_qsl_test_cases_legacy = [ -+ (b"a=1;a=2&a=3", [(b'a', b'1'), (b'a', b'2'), (b'a', b'3')]), -+ (b"a=1;b=2&c=3", [(b'a', b'1'), (b'b', b'2'), (b'c', b'3')]), -+ (b"a=1&b=2&c=3;", [(b'a', b'1'), (b'b', b'2'), (b'c', b'3')]), -+] -+ -+parse_qsl_test_cases_warn = [ - (";a=b", [(';a', 'b')]), - ("a=a+b;b=b+c", [('a', 'a b;b=b c')]), - (b";a=b", [(b';a', b'b')]), - (b"a=a+b;b=b+c", [(b'a', b'a b;b=b c')]), -+ ("a=1;a=2&a=3", [('a', '1;a=2'), ('a', '3')]), -+ (b"a=1;a=2&a=3", [(b'a', b'1;a=2'), (b'a', b'3')]), - ] - - # Each parse_qs testcase is a two-tuple that contains -@@ -62,10 +91,37 @@ parse_qs_test_cases = [ - (b"&a=b", {b'a': [b'b']}), - (b"a=a+b&b=b+c", {b'a': [b'a b'], b'b': [b'b c']}), - (b"a=1&a=2", {b'a': [b'1', b'2']}), -+] -+ -+parse_qs_test_cases_semicolon = [ -+ (";", {}), -+ (";;", {}), -+ (";a=b", {'a': ['b']}), -+ ("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}), -+ ("a=1;a=2", {'a': ['1', '2']}), -+ (b";", {}), -+ (b";;", {}), -+ (b";a=b", {b'a': [b'b']}), -+ (b"a=a+b;b=b+c", {b'a': [b'a b'], b'b': [b'b c']}), -+ (b"a=1;a=2", {b'a': [b'1', b'2']}), -+] -+ -+parse_qs_test_cases_legacy = [ -+ ("a=1;a=2&a=3", {'a': ['1', '2', '3']}), -+ ("a=1;b=2&c=3", {'a': ['1'], 'b': ['2'], 'c': ['3']}), -+ ("a=1&b=2&c=3;", {'a': ['1'], 'b': ['2'], 'c': ['3']}), -+ (b"a=1;a=2&a=3", {b'a': [b'1', b'2', b'3']}), -+ (b"a=1;b=2&c=3", {b'a': [b'1'], b'b': [b'2'], b'c': [b'3']}), -+ (b"a=1&b=2&c=3;", {b'a': [b'1'], b'b': [b'2'], b'c': [b'3']}), -+] -+ -+parse_qs_test_cases_warn = [ - (";a=b", {';a': ['b']}), - ("a=a+b;b=b+c", {'a': ['a b;b=b c']}), - (b";a=b", {b';a': [b'b']}), - (b"a=a+b;b=b+c", {b'a':[ b'a b;b=b c']}), -+ ("a=1;a=2&a=3", {'a': ['1;a=2', '3']}), -+ (b"a=1;a=2&a=3", {b'a': [b'1;a=2', b'3']}), - ] - - class UrlParseTestCase(unittest.TestCase): -@@ -123,23 +179,57 @@ class UrlParseTestCase(unittest.TestCase): - - def test_qsl(self): - for orig, expect in parse_qsl_test_cases: -- result = urllib.parse.parse_qsl(orig, keep_blank_values=True) -+ result = urllib.parse.parse_qsl(orig, keep_blank_values=True, separator="&") - self.assertEqual(result, expect, "Error parsing %r" % orig) - expect_without_blanks = [v for v in expect if len(v[1])] -- result = urllib.parse.parse_qsl(orig, keep_blank_values=False) -+ result = urllib.parse.parse_qsl(orig, keep_blank_values=False, separator="&") - self.assertEqual(result, expect_without_blanks, - "Error parsing %r" % orig) - - def test_qs(self): - for orig, expect in parse_qs_test_cases: -- result = urllib.parse.parse_qs(orig, keep_blank_values=True) -+ result = urllib.parse.parse_qs(orig, keep_blank_values=True, separator="&") - self.assertEqual(result, expect, "Error parsing %r" % orig) - expect_without_blanks = {v: expect[v] - for v in expect if len(expect[v][0])} -- result = urllib.parse.parse_qs(orig, keep_blank_values=False) -+ result = urllib.parse.parse_qs(orig, keep_blank_values=False, separator="&") - self.assertEqual(result, expect_without_blanks, - "Error parsing %r" % orig) - -+ def test_qs_default_warn(self): -+ for orig, expect in parse_qs_test_cases_warn: -+ with self.subTest(orig=orig, expect=expect): -+ with catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qs(orig, keep_blank_values=True) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 1) -+ self.assertEqual(w[0].category, urllib.parse._QueryStringSeparatorWarning) -+ -+ def test_qsl_default_warn(self): -+ for orig, expect in parse_qsl_test_cases_warn: -+ with self.subTest(orig=orig, expect=expect): -+ with catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qsl(orig, keep_blank_values=True) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 1) -+ self.assertEqual(w[0].category, urllib.parse._QueryStringSeparatorWarning) -+ -+ def test_default_qs_no_warnings(self): -+ for orig, expect in parse_qs_test_cases: -+ with self.subTest(orig=orig, expect=expect): -+ with catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qs(orig, keep_blank_values=True) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ -+ def test_default_qsl_no_warnings(self): -+ for orig, expect in parse_qsl_test_cases: -+ with self.subTest(orig=orig, expect=expect): -+ with catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qsl(orig, keep_blank_values=True) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ - def test_roundtrips(self): - str_cases = [ - ('file:///tmp/junk.txt', -@@ -919,8 +1009,8 @@ class UrlParseTestCase(unittest.TestCase): - - def test_parse_qsl_max_num_fields(self): - with self.assertRaises(ValueError): -- urllib.parse.parse_qs('&'.join(['a=a']*11), max_num_fields=10) -- urllib.parse.parse_qs('&'.join(['a=a']*10), max_num_fields=10) -+ urllib.parse.parse_qs('&'.join(['a=a']*11), max_num_fields=10, separator='&') -+ urllib.parse.parse_qs('&'.join(['a=a']*10), max_num_fields=10, separator='&') - - def test_parse_qs_separator(self): - parse_qs_semicolon_cases = [ -@@ -964,6 +1054,136 @@ class UrlParseTestCase(unittest.TestCase): - self.assertEqual(result_bytes, expect, "Error parsing %r" % orig) - - -+ @contextlib.contextmanager -+ def _qsl_sep_config(self, sep): -+ """Context for the given parse_qsl default separator configured in config file""" -+ old_filename = urllib.parse._QS_SEPARATOR_CONFIG_FILENAME -+ urllib.parse._default_qs_separator = None -+ try: -+ with tempfile.TemporaryDirectory() as tmpdirname: -+ filename = os.path.join(tmpdirname, 'conf.cfg') -+ with open(filename, 'w') as file: -+ file.write(f'[parse_qs]\n') -+ file.write(f'PYTHON_URLLIB_QS_SEPARATOR = {sep}') -+ urllib.parse._QS_SEPARATOR_CONFIG_FILENAME = filename -+ yield -+ finally: -+ urllib.parse._QS_SEPARATOR_CONFIG_FILENAME = old_filename -+ urllib.parse._default_qs_separator = None -+ -+ def test_parse_qs_separator_semicolon(self): -+ for orig, expect in parse_qs_test_cases_semicolon: -+ with self.subTest(orig=orig, expect=expect, method='arg'): -+ result = urllib.parse.parse_qs(orig, separator=';') -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ with self.subTest(orig=orig, expect=expect, method='env'): -+ with EnvironmentVarGuard() as environ, catch_warnings(record=True) as w: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = ';' -+ result = urllib.parse.parse_qs(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ with self.subTest(orig=orig, expect=expect, method='conf'): -+ with self._qsl_sep_config(';'), catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qs(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ -+ def test_parse_qsl_separator_semicolon(self): -+ for orig, expect in parse_qsl_test_cases_semicolon: -+ with self.subTest(orig=orig, expect=expect, method='arg'): -+ result = urllib.parse.parse_qsl(orig, separator=';') -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ with self.subTest(orig=orig, expect=expect, method='env'): -+ with EnvironmentVarGuard() as environ, catch_warnings(record=True) as w: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = ';' -+ result = urllib.parse.parse_qsl(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ with self.subTest(orig=orig, expect=expect, method='conf'): -+ with self._qsl_sep_config(';'), catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qsl(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ -+ def test_parse_qs_separator_legacy(self): -+ for orig, expect in parse_qs_test_cases_legacy: -+ with self.subTest(orig=orig, expect=expect, method='env'): -+ with EnvironmentVarGuard() as environ, catch_warnings(record=True) as w: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = 'legacy' -+ result = urllib.parse.parse_qs(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ with self.subTest(orig=orig, expect=expect, method='conf'): -+ with self._qsl_sep_config('legacy'), catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qs(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ -+ def test_parse_qsl_separator_legacy(self): -+ for orig, expect in parse_qsl_test_cases_legacy: -+ with self.subTest(orig=orig, expect=expect, method='env'): -+ with EnvironmentVarGuard() as environ, catch_warnings(record=True) as w: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = 'legacy' -+ result = urllib.parse.parse_qsl(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ with self.subTest(orig=orig, expect=expect, method='conf'): -+ with self._qsl_sep_config('legacy'), catch_warnings(record=True) as w: -+ result = urllib.parse.parse_qsl(orig) -+ self.assertEqual(result, expect, "Error parsing %r" % orig) -+ self.assertEqual(len(w), 0) -+ -+ def test_parse_qs_separator_bad_value_env_or_config(self): -+ for bad_sep in '', 'abc', 'safe', '&;', 'SEP': -+ with self.subTest(bad_sep, method='env'): -+ with EnvironmentVarGuard() as environ, catch_warnings(record=True) as w: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = bad_sep -+ with self.assertRaises(ValueError): -+ urllib.parse.parse_qsl('a=1;b=2') -+ with self.subTest(bad_sep, method='conf'): -+ with self._qsl_sep_config('bad_sep'), catch_warnings(record=True) as w: -+ with self.assertRaises(ValueError): -+ urllib.parse.parse_qsl('a=1;b=2') -+ -+ def test_parse_qs_separator_bad_value_arg(self): -+ for bad_sep in True, {}, '': -+ with self.subTest(bad_sep): -+ with self.assertRaises(ValueError): -+ urllib.parse.parse_qsl('a=1;b=2', separator=bad_sep) -+ -+ def test_parse_qs_separator_num_fields(self): -+ for qs, sep in ( -+ ('a&b&c', '&'), -+ ('a;b;c', ';'), -+ ('a&b;c', 'legacy'), -+ ): -+ with self.subTest(qs=qs, sep=sep): -+ with EnvironmentVarGuard() as environ, catch_warnings(record=True) as w: -+ if sep != 'legacy': -+ with self.assertRaises(ValueError): -+ urllib.parse.parse_qsl(qs, separator=sep, max_num_fields=2) -+ if sep: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = sep -+ with self.assertRaises(ValueError): -+ urllib.parse.parse_qsl(qs, max_num_fields=2) -+ -+ def test_parse_qs_separator_priority(self): -+ # env variable trumps config file -+ with self._qsl_sep_config('~'), EnvironmentVarGuard() as environ: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = '!' -+ result = urllib.parse.parse_qs('a=1!b=2~c=3') -+ self.assertEqual(result, {'a': ['1'], 'b': ['2~c=3']}) -+ # argument trumps config file -+ with self._qsl_sep_config('~'): -+ result = urllib.parse.parse_qs('a=1$b=2~c=3', separator='$') -+ self.assertEqual(result, {'a': ['1'], 'b': ['2~c=3']}) -+ # argument trumps env variable -+ with EnvironmentVarGuard() as environ: -+ environ['PYTHON_URLLIB_QS_SEPARATOR'] = '~' -+ result = urllib.parse.parse_qs('a=1$b=2~c=3', separator='$') -+ self.assertEqual(result, {'a': ['1'], 'b': ['2~c=3']}) -+ -+ - def test_urlencode_sequences(self): - # Other tests incidentally urlencode things; test non-covered cases: - # Sequence and object values. -diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py -index f0d9d4d..70fc268 100644 ---- a/Lib/urllib/parse.py -+++ b/Lib/urllib/parse.py -@@ -28,6 +28,7 @@ test_urlparse.py provides a good indicator of parsing behavior. - """ - - import re -+import os - import sys - import collections - import warnings -@@ -660,7 +661,7 @@ def unquote(string, encoding='utf-8', errors='replace'): - - - def parse_qs(qs, keep_blank_values=False, strict_parsing=False, -- encoding='utf-8', errors='replace', max_num_fields=None, separator='&'): -+ encoding='utf-8', errors='replace', max_num_fields=None, separator=None): - """Parse a query given as a string argument. - - Arguments: -@@ -700,9 +701,16 @@ def parse_qs(qs, keep_blank_values=False, strict_parsing=False, - parsed_result[name] = [value] - return parsed_result - -+class _QueryStringSeparatorWarning(RuntimeWarning): -+ """Warning for using default `separator` in parse_qs or parse_qsl""" -+ -+# The default "separator" for parse_qsl can be specified in a config file. -+# It's cached after first read. -+_QS_SEPARATOR_CONFIG_FILENAME = '/etc/python/urllib.cfg' -+_default_qs_separator = None - - def parse_qsl(qs, keep_blank_values=False, strict_parsing=False, -- encoding='utf-8', errors='replace', max_num_fields=None, separator='&'): -+ encoding='utf-8', errors='replace', max_num_fields=None, separator=None): - """Parse a query given as a string argument. - - Arguments: -@@ -731,20 +739,78 @@ def parse_qsl(qs, keep_blank_values=False, strict_parsing=False, - Returns a list, as G-d intended. - """ - qs, _coerce_result = _coerce_args(qs) -- separator, _ = _coerce_args(separator) - -- if not separator or (not isinstance(separator, (str, bytes))): -+ if isinstance(separator, bytes): -+ separator = separator.decode('ascii') -+ -+ if (not separator or (not isinstance(separator, (str, bytes)))) and separator is not None: - raise ValueError("Separator must be of type string or bytes.") - -+ # Used when both "&" and ";" act as separators. (Need a non-string value.) -+ _legacy = object() -+ -+ if separator is None: -+ global _default_qs_separator -+ separator = _default_qs_separator -+ envvar_name = 'PYTHON_URLLIB_QS_SEPARATOR' -+ if separator is None: -+ # Set default separator from environment variable -+ separator = os.environ.get(envvar_name) -+ config_source = 'environment variable' -+ if separator is None: -+ # Set default separator from the configuration file -+ try: -+ file = open(_QS_SEPARATOR_CONFIG_FILENAME) -+ except FileNotFoundError: -+ pass -+ else: -+ with file: -+ import configparser -+ config = configparser.ConfigParser( -+ interpolation=None, -+ comment_prefixes=('#', ), -+ ) -+ config.read_file(file) -+ separator = config.get('parse_qs', envvar_name, fallback=None) -+ _default_qs_separator = separator -+ config_source = _QS_SEPARATOR_CONFIG_FILENAME -+ if separator is None: -+ # The default is '&', but warn if not specified explicitly -+ if ';' in qs: -+ from warnings import warn -+ warn("The default separator of urllib.parse.parse_qsl and " -+ + "parse_qs was changed to '&' to avoid a web cache " -+ + "poisoning issue (CVE-2021-23336). " -+ + "By default, semicolons no longer act as query field " -+ + "separators. " -+ + "See https://access.redhat.com/articles/5860431 for " -+ + "more details.", -+ _QueryStringSeparatorWarning, stacklevel=2) -+ separator = '&' -+ elif separator == 'legacy': -+ separator = _legacy -+ elif len(separator) != 1: -+ raise ValueError( -+ f'{envvar_name} (from {config_source}) must contain ' -+ + '1 character, or "legacy". See ' -+ + 'https://access.redhat.com/articles/5860431 for more details.' -+ ) -+ - # If max_num_fields is defined then check that the number of fields - # is less than max_num_fields. This prevents a memory exhaustion DOS - # attack via post bodies with many fields. - if max_num_fields is not None: -- num_fields = 1 + qs.count(separator) -+ if separator is _legacy: -+ num_fields = 1 + qs.count('&') + qs.count(';') -+ else: -+ num_fields = 1 + qs.count(separator) - if max_num_fields < num_fields: - raise ValueError('Max number of fields exceeded') - -- pairs = [s1 for s1 in qs.split(separator)] -+ if separator is _legacy: -+ pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')] -+ else: -+ pairs = [s1 for s1 in qs.split(separator)] - r = [] - for name_value in pairs: - if not name_value and not strict_parsing: --- -2.31.1 - diff --git a/SOURCES/00378-support-expat-2-4-5.patch b/SOURCES/00378-support-expat-2-4-5.patch deleted file mode 100644 index 2a06bfb..0000000 --- a/SOURCES/00378-support-expat-2-4-5.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py -index 06c9107..6c3f5a8 100644 ---- a/Lib/test/test_minidom.py -+++ b/Lib/test/test_minidom.py -@@ -1149,14 +1149,11 @@ class MinidomTest(unittest.TestCase): - - # Verify that character decoding errors raise exceptions instead - # of crashing -- if pyexpat.version_info >= (2, 4, 5): -- self.assertRaises(ExpatError, parseString, -- b'') -- self.assertRaises(ExpatError, parseString, -- b'Comment \xe7a va ? Tr\xe8s bien ?') -- else: -- self.assertRaises(UnicodeDecodeError, parseString, -- b'Comment \xe7a va ? Tr\xe8s bien ?') -+ -+ self.assertRaises(ExpatError, parseString, -+ b'') -+ self.assertRaises(ExpatError, parseString, -+ b'Comment \xe7a va ? Tr\xe8s bien ?') - - doc.unlink() - -@@ -1601,10 +1598,7 @@ class MinidomTest(unittest.TestCase): - self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE) - - def testExceptionOnSpacesInXMLNSValue(self): -- if pyexpat.version_info >= (2, 4, 5): -- context = self.assertRaisesRegex(ExpatError, 'syntax error') -- else: -- context = self.assertRaisesRegex(ValueError, 'Unsupported syntax') -+ context = self.assertRaisesRegex(ExpatError, 'syntax error') - - with context: - parseString('') diff --git a/SOURCES/00397-tarfile-filter.patch b/SOURCES/00397-tarfile-filter.patch deleted file mode 100644 index 135c595..0000000 --- a/SOURCES/00397-tarfile-filter.patch +++ /dev/null @@ -1,357 +0,0 @@ -From f36519078bde3cce4328c03fffccb846121fb5bc Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Wed, 9 Aug 2023 20:23:03 +0200 -Subject: [PATCH] Fix symlink handling for tarfile.data_filter - ---- - Doc/library/tarfile.rst | 5 +++++ - Lib/tarfile.py | 9 ++++++++- - Lib/test/test_tarfile.py | 26 ++++++++++++++++++++++++-- - 3 files changed, 37 insertions(+), 3 deletions(-) - -diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst -index 00f3070324e..e0511bfeb64 100644 ---- a/Doc/library/tarfile.rst -+++ b/Doc/library/tarfile.rst -@@ -740,6 +740,11 @@ A ``TarInfo`` object has the following public data attributes: - Name of the target file name, which is only present in :class:`TarInfo` objects - of type :const:`LNKTYPE` and :const:`SYMTYPE`. - -+ For symbolic links (``SYMTYPE``), the linkname is relative to the directory -+ that contains the link. -+ For hard links (``LNKTYPE``), the linkname is relative to the root of -+ the archive. -+ - - .. attribute:: TarInfo.uid - :type: int -diff --git a/Lib/tarfile.py b/Lib/tarfile.py -index df4e41f7a0d..d62323715b4 100755 ---- a/Lib/tarfile.py -+++ b/Lib/tarfile.py -@@ -802,7 +802,14 @@ def _get_filtered_attrs(member, dest_path, for_data=True): - if member.islnk() or member.issym(): - if os.path.isabs(member.linkname): - raise AbsoluteLinkError(member) -- target_path = os.path.realpath(os.path.join(dest_path, member.linkname)) -+ if member.issym(): -+ target_path = os.path.join(dest_path, -+ os.path.dirname(name), -+ member.linkname) -+ else: -+ target_path = os.path.join(dest_path, -+ member.linkname) -+ target_path = os.path.realpath(target_path) - if os.path.commonpath([target_path, dest_path]) != dest_path: - raise LinkOutsideDestinationError(member, target_path) - return new_attrs -diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index 2eda7fc4cea..79fc35c2895 100644 ---- a/Lib/test/test_tarfile.py -+++ b/Lib/test/test_tarfile.py -@@ -3337,10 +3337,12 @@ def __exit__(self, *exc): - self.bio = None - - def add(self, name, *, type=None, symlink_to=None, hardlink_to=None, -- mode=None, **kwargs): -+ mode=None, size=None, **kwargs): - """Add a member to the test archive. Call within `with`.""" - name = str(name) - tarinfo = tarfile.TarInfo(name).replace(**kwargs) -+ if size is not None: -+ tarinfo.size = size - if mode: - tarinfo.mode = _filemode_to_int(mode) - if symlink_to is not None: -@@ -3416,7 +3418,8 @@ def check_context(self, tar, filter): - raise self.raised_exception - self.assertEqual(self.expected_paths, set()) - -- def expect_file(self, name, type=None, symlink_to=None, mode=None): -+ def expect_file(self, name, type=None, symlink_to=None, mode=None, -+ size=None): - """Check a single file. See check_context.""" - if self.raised_exception: - raise self.raised_exception -@@ -3445,6 +3448,8 @@ def expect_file(self, name, type=None, symlink_to=None, mode=None): - self.assertTrue(path.is_fifo()) - else: - raise NotImplementedError(type) -+ if size is not None: -+ self.assertEqual(path.stat().st_size, size) - for parent in path.parents: - self.expected_paths.discard(parent) - -@@ -3649,6 +3654,22 @@ def test_sly_relative2(self): - + """['"].*moo['"], which is outside the """ - + "destination") - -+ def test_deep_symlink(self): -+ with ArchiveMaker() as arc: -+ arc.add('targetdir/target', size=3) -+ arc.add('linkdir/hardlink', hardlink_to='targetdir/target') -+ arc.add('linkdir/symlink', symlink_to='../targetdir/target') -+ -+ for filter in 'tar', 'data', 'fully_trusted': -+ with self.check_context(arc.open(), filter): -+ self.expect_file('targetdir/target', size=3) -+ self.expect_file('linkdir/hardlink', size=3) -+ if support.can_symlink(): -+ self.expect_file('linkdir/symlink', size=3, -+ symlink_to='../targetdir/target') -+ else: -+ self.expect_file('linkdir/symlink', size=3) -+ - def test_modes(self): - # Test how file modes are extracted - # (Note that the modes are ignored on platforms without working chmod) --- -2.41.0 - -From dc84087083c5ad99a5016e8349c96d9654a08f46 Mon Sep 17 00:00:00 2001 -From: Petr Viktorin -Date: Mon, 6 Mar 2023 17:24:24 +0100 -Subject: [PATCH 2/2] CVE-2007-4559, PEP-706: Add filters for tarfile - extraction (downstream) - -Add and test RHEL-specific ways of configuring the default behavior: environment -variable and config file. ---- - Lib/tarfile.py | 42 +++++++++++++ - Lib/test/test_shutil.py | 3 +- - Lib/test/test_tarfile.py | 124 ++++++++++++++++++++++++++++++++++++++- - 3 files changed, 165 insertions(+), 4 deletions(-) - -diff --git a/Lib/tarfile.py b/Lib/tarfile.py -index 5291622ab8e..12ab00d748a 100755 ---- a/Lib/tarfile.py -+++ b/Lib/tarfile.py -@@ -72,6 +72,13 @@ __all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError", "ReadError", - "ENCODING", "USTAR_FORMAT", "GNU_FORMAT", "PAX_FORMAT", - "DEFAULT_FORMAT", "open"] - -+# If true, use the safer (but backwards-incompatible) 'tar' extraction filter, -+# rather than 'fully_trusted', by default. -+# The emitted warning is changed to match. -+_RH_SAFER_DEFAULT = True -+ -+# System-wide configuration file -+_CONFIG_FILENAME = '/etc/python/tarfile.cfg' - - #--------------------------------------------------------- - # tar constants -@@ -2188,6 +2195,41 @@ class TarFile(object): - if filter is None: - filter = self.extraction_filter - if filter is None: -+ name = os.environ.get('PYTHON_TARFILE_EXTRACTION_FILTER') -+ if name is None: -+ try: -+ file = bltn_open(_CONFIG_FILENAME) -+ except FileNotFoundError: -+ pass -+ else: -+ import configparser -+ conf = configparser.ConfigParser( -+ interpolation=None, -+ comment_prefixes=('#', ), -+ ) -+ with file: -+ conf.read_file(file) -+ name = conf.get('tarfile', -+ 'PYTHON_TARFILE_EXTRACTION_FILTER', -+ fallback='') -+ if name: -+ try: -+ filter = _NAMED_FILTERS[name] -+ except KeyError: -+ raise ValueError(f"filter {filter!r} not found") from None -+ self.extraction_filter = filter -+ return filter -+ if _RH_SAFER_DEFAULT: -+ warnings.warn( -+ 'The default behavior of tarfile extraction has been ' -+ + 'changed to disallow common exploits ' -+ + '(including CVE-2007-4559). ' -+ + 'By default, absolute/parent paths are disallowed ' -+ + 'and some mode bits are cleared. ' -+ + 'See https://access.redhat.com/articles/7004769 ' -+ + 'for more details.', -+ RuntimeWarning) -+ return tar_filter - return fully_trusted_filter - if isinstance(filter, str): - raise TypeError( -diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py -index 5cef59ea9c6..73fffe0fd33 100644 ---- a/Lib/test/test_shutil.py -+++ b/Lib/test/test_shutil.py -@@ -1494,7 +1494,8 @@ class TestShutil(unittest.TestCase): - def check_unpack_tarball(self, format): - self.check_unpack_archive(format, filter='fully_trusted') - self.check_unpack_archive(format, filter='data') -- with support.check_no_warnings(self): -+ with support.check_warnings( -+ ('.*CVE-2007-4559', RuntimeWarning)): - self.check_unpack_archive(format) - - def test_unpack_archive_tar(self): -diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index 03be10b1fee..15df6a9ced6 100644 ---- a/Lib/test/test_tarfile.py -+++ b/Lib/test/test_tarfile.py -@@ -2,7 +2,7 @@ - import os - import io - from hashlib import sha256 --from contextlib import contextmanager -+from contextlib import contextmanager, ExitStack - from random import Random - import pathlib - import shutil -@@ -2744,7 +2744,11 @@ class NoneInfoExtractTests(ReadTest): - tar = tarfile.open(tarname, mode='r', encoding="iso8859-1") - cls.control_dir = pathlib.Path(TEMPDIR) / "extractall_ctrl" - tar.errorlevel = 0 -- tar.extractall(cls.control_dir, filter=cls.extraction_filter) -+ with ExitStack() as cm: -+ if cls.extraction_filter is None: -+ cm.enter_context(warnings.catch_warnings()) -+ warnings.simplefilter(action="ignore", category=RuntimeWarning) -+ tar.extractall(cls.control_dir, filter=cls.extraction_filter) - tar.close() - cls.control_paths = set( - p.relative_to(cls.control_dir) -@@ -3407,7 +3411,8 @@ class TestExtractionFilters(unittest.TestCase): - """Ensure the default filter does not warn (like in 3.12)""" - with ArchiveMaker() as arc: - arc.add('foo') -- with support.check_no_warnings(self): -+ with support.check_warnings( -+ ('.*CVE-2007-4559', RuntimeWarning)): - with self.check_context(arc.open(), None): - self.expect_file('foo') - -@@ -3577,6 +3582,119 @@ class TestExtractionFilters(unittest.TestCase): - self.expect_exception(TypeError) # errorlevel is not int - - -+ @contextmanager -+ def rh_config_context(self, config_lines=None): -+ """Set up for testing various ways of overriding the default filter -+ -+ return a triple with: -+ - temporary directory -+ - EnvironmentVarGuard() -+ - a test archive for use with check_* methods below -+ -+ If config_lines is given, write them to the config file. Otherwise -+ the config file is missing. -+ """ -+ tempdir = pathlib.Path(TEMPDIR) / 'tmp' -+ configfile = tempdir / 'tarfile.cfg' -+ with ArchiveMaker() as arc: -+ arc.add('good') -+ arc.add('ugly', symlink_to='/etc/passwd') -+ arc.add('../bad') -+ with ExitStack() as cm: -+ cm.enter_context(support.temp_dir(tempdir)) -+ cm.enter_context(support.swap_attr(tarfile, '_CONFIG_FILENAME', str(configfile))) -+ env = cm.enter_context(support.EnvironmentVarGuard()) -+ tar = cm.enter_context(arc.open()) -+ if config_lines is not None: -+ with configfile.open('w') as f: -+ for line in config_lines: -+ print(line, file=f) -+ yield tempdir, env, tar -+ -+ def check_rh_default_behavior(self, tar, tempdir): -+ """Check RH default: warn and refuse to extract dangerous files.""" -+ with ExitStack() as cm: -+ cm.enter_context(support.check_warnings( -+ ('.*CVE-2007-4559', RuntimeWarning))) -+ cm.enter_context(self.assertRaises(tarfile.OutsideDestinationError)) -+ tar.extractall(tempdir / 'outdir') -+ -+ def check_trusted_default(self, tar, tempdir): -+ """Check 'fully_trusted' is configured as the default filter.""" -+ with support.check_no_warnings(self): -+ tar.extractall(tempdir / 'outdir') -+ self.assertTrue((tempdir / 'outdir/good').exists()) -+ self.assertEqual(os.readlink(str(tempdir / 'outdir/ugly')), -+ '/etc/passwd') -+ self.assertTrue((tempdir / 'bad').exists()) -+ -+ def test_rh_default_no_conf(self): -+ with self.rh_config_context() as (tempdir, env, tar): -+ self.check_rh_default_behavior(tar, tempdir) -+ -+ def test_rh_default_from_file(self): -+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=fully_trusted'] -+ with self.rh_config_context(lines) as (tempdir, env, tar): -+ self.check_trusted_default(tar, tempdir) -+ -+ def test_rh_empty_config_file(self): -+ """Empty config file -> default behavior""" -+ lines = [] -+ with self.rh_config_context(lines) as (tempdir, env, tar): -+ self.check_rh_default_behavior(tar, tempdir) -+ -+ def test_empty_config_section(self): -+ """Empty section in config file -> default behavior""" -+ lines = ['[tarfile]'] -+ with self.rh_config_context(lines) as (tempdir, env, tar): -+ self.check_rh_default_behavior(tar, tempdir) -+ -+ def test_rh_default_empty_config_option(self): -+ """Empty option value in config file -> default behavior""" -+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER='] -+ with self.rh_config_context(lines) as (tempdir, env, tar): -+ self.check_rh_default_behavior(tar, tempdir) -+ -+ def test_bad_config_option(self): -+ """Bad option value in config file -> ValueError""" -+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=unknown!'] -+ with self.rh_config_context(lines) as (tempdir, env, tar): -+ with self.assertRaises(ValueError): -+ tar.extractall(tempdir / 'outdir') -+ -+ def test_default_from_envvar(self): -+ with self.rh_config_context() as (tempdir, env, tar): -+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'fully_trusted' -+ self.check_trusted_default(tar, tempdir) -+ -+ def test_empty_envvar(self): -+ """Empty env variable -> default behavior""" -+ with self.rh_config_context() as (tempdir, env, tar): -+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = '' -+ self.check_rh_default_behavior(tar, tempdir) -+ -+ def test_bad_envvar(self): -+ with self.rh_config_context() as (tempdir, env, tar): -+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'unknown!' -+ with self.assertRaises(ValueError): -+ tar.extractall(tempdir / 'outdir') -+ -+ def test_envvar_overrides_file(self): -+ lines = ['[tarfile]', 'PYTHON_TARFILE_EXTRACTION_FILTER=data'] -+ with self.rh_config_context(lines) as (tempdir, env, tar): -+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'fully_trusted' -+ self.check_trusted_default(tar, tempdir) -+ -+ def test_monkeypatch_overrides_envvar(self): -+ with self.rh_config_context(None) as (tempdir, env, tar): -+ env['PYTHON_TARFILE_EXTRACTION_FILTER'] = 'data' -+ with support.swap_attr( -+ tarfile.TarFile, 'extraction_filter', -+ staticmethod(tarfile.fully_trusted_filter) -+ ): -+ self.check_trusted_default(tar, tempdir) -+ -+ - def setUpModule(): - support.unlink(TEMPDIR) - os.makedirs(TEMPDIR) --- -2.41.0 - diff --git a/SPECS/python38.spec b/SPECS/python38.spec index bac3497..96e2183 100644 --- a/SPECS/python38.spec +++ b/SPECS/python38.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}.6 #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 2%{?dist} +Release: 3%{?dist} License: Python # Exclude i686 arch. Due to a modularity issue it's being added to the @@ -350,47 +350,11 @@ Patch329: 00329-fips.patch # a nightmare because it's basically a binary file. Patch353: 00353-architecture-names-upstream-downstream.patch -# 00359 # -# CVE-2021-23336 python: Web Cache Poisoning via urllib.parse.parse_qsl and -# urllib.parse.parse_qs by using a semicolon in query parameters -# Upstream: https://bugs.python.org/issue42967 -# Main BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1928904 -Patch359: 00359-CVE-2021-23336.patch - -# 00378 # -# Support expat 2.4.5 -# -# Curly brackets were never allowed in namespace URIs -# according to RFC 3986, and so-called namespace-validating -# XML parsers have the right to reject them a invalid URIs. -# -# libexpat >=2.4.5 has become strcter in that regard due to -# related security issues; with ET.XML instantiating a -# namespace-aware parser under the hood, this test has no -# future in CPython. -# -# References: -# - https://datatracker.ietf.org/doc/html/rfc3968 -# - https://www.w3.org/TR/xml-names/ -# -# Also, test_minidom.py: Support Expat >=2.4.5 -# -# The patch has diverged from upstream as the python test -# suite was relying on checking the expat version, whereas -# in RHEL fixes get backported instead of rebasing packages. -# -# Upstream: https://bugs.python.org/issue46811 -Patch378: 00378-support-expat-2-4-5.patch - -# 00397 # -# Add filters for tarfile extraction (CVE-2007-4559, PEP-706) -# First patch fixes determination of symlink targets, which were treated -# as relative to the root of the archive, -# rather than the directory containing the symlink. -# Not yet upstream as of this writing. -# The second patch is Red Hat configuration, see KB for documentation: -# - https://access.redhat.com/articles/7004769 -Patch397: 00397-tarfile-filter.patch +# 00357 # +# Security fix for CVE-2021-3177 +# Stack-based buffer overflow in PyCArg_repr in _ctypes/callproc.c +# Resolves upstream: https://bugs.python.org/issue42938 +Patch357: 00357-CVE-2021-3177.patch # (New patches go here ^^^) # @@ -418,10 +382,10 @@ Provides: python%{pybasever} = %{version}-%{release} # the possible alternatives Provides: alternative-for(python) -# Require alternatives version that implements the --keep-foreign flag -Requires: alternatives >= 1.19.1-1 -Requires(post): alternatives >= 1.19.1-1 -Requires(postun): alternatives >= 1.19.1-1 +# Runtime require alternatives +Requires: %{_sbindir}/alternatives +Requires(post): %{_sbindir}/alternatives +Requires(postun): %{_sbindir}/alternatives %if %{without flatpackage} @@ -515,8 +479,8 @@ Summary: Python runtime libraries Requires: python38-setuptools-wheel Requires: python38-pip-wheel %else -Provides: bundled(python38-pip) = 23.0.1 -Provides: bundled(python38-setuptools) = 56.0.0 +Provides: bundled(python38-pip) = 19.2.3 +Provides: bundled(python38-setuptools) = 41.2.0 %endif %{?python_provide:%python_provide python38-libs} @@ -548,9 +512,6 @@ BuildRequires: python-rpm-macros # But we want them when packages BuildRequire python3-devel Requires: (python-rpm-macros if rpm-build) Requires: (python3-rpm-macros if rpm-build) - -# Require alternatives version that implements the --keep-foreign flag -Requires(postun): alternatives >= 1.19.1-1 # python38 installs the alternatives master symlink to which we attach a slave Requires(post): python38 Requires(postun): python38 @@ -589,8 +550,6 @@ Requires: %{name}-tkinter = %{version}-%{release} %{?python_provide:%python_provide python38-idle} -# Require alternatives version that implements the --keep-foreign flag -Requires(postun): alternatives >= 1.19.1-1 # python38 installs the alternatives master symlink to which we attach a slave Requires(post): python38 Requires(postun): python38 @@ -647,9 +606,6 @@ Requires: %{name}-devel%{?_isa} = %{version}-%{release} Requires: %{name}-test%{?_isa} = %{version}-%{release} Requires: %{name}-tkinter%{?_isa} = %{version}-%{release} Requires: %{name}-idle%{?_isa} = %{version}-%{release} - -# Require alternatives version that implements the --keep-foreign flag -Requires(postun): alternatives >= 1.19.1-1 # python38 installs the alternatives master symlink to which we attach a slave Requires(post): python38 Requires(postun): python38 @@ -684,8 +640,8 @@ The debug runtime additionally supports debug builds of C-API extensions Requires: python38-setuptools-wheel Requires: python38-pip-wheel %else -Provides: bundled(python38-pip) = 23.0.1 -Provides: bundled(python38-setuptools) = 56.0.0 +Provides: bundled(python38-pip) = 19.2.3 +Provides: bundled(python38-setuptools) = 41.2.0 %endif # The description for the flat package @@ -747,9 +703,8 @@ rm Lib/ensurepip/_bundled/*.whl %patch328 -p1 %patch329 -p1 %patch353 -p1 -%patch359 -p1 -%patch378 -p1 -%patch397 -p1 +%patch357 -p1 + # Remove files that should be generated by the build # (This is after patching, so that we can use patches directly from upstream) @@ -1132,11 +1087,6 @@ touch %{buildroot}%{_bindir}/python3-config touch %{buildroot}%{_bindir}/python3-debug touch %{buildroot}%{_bindir}/python3-debug-config -# Strip the LTO bytecode from python.o -# Based on the fedora brp-strip-lto scriptlet -# https://src.fedoraproject.org/rpms/redhat-rpm-config/blob/9dd5528cf9805ebfe31cff04fe7828ad06a6023f/f/brp-strip-lto -find %{buildroot} -type f -name 'python.o' -print0 | xargs -0 \ -bash -c "strip -p -R .gnu.lto_* -R .gnu.debuglto_* -N __gnu_lto_v1 \"\$@\"" ARG0 # ====================================================== # Checks for packaging issues @@ -1274,15 +1224,15 @@ fi %postun # Do this only during uninstall process (not during update) if [ $1 -eq 0 ]; then - alternatives --keep-foreign --remove python \ + alternatives --remove python \ %{_bindir}/python3.8 - alternatives --keep-foreign --remove python3 \ + alternatives --remove python3 \ %{_bindir}/python3.8 # Remove link python → python3 if no other python3.* exists if ! alternatives --display python3 > /dev/null; then - alternatives --keep-foreign --remove python \ + alternatives --remove python \ %{_bindir}/python3 fi fi @@ -1297,7 +1247,7 @@ alternatives --add-slave python3 %{_bindir}/python3.8 \ %postun devel # Do this only during uninstall process (not during update) if [ $1 -eq 0 ]; then - alternatives --keep-foreign --remove-slave python3 %{_bindir}/python3.8 \ + alternatives --remove-slave python3 %{_bindir}/python3.8 \ python3-config fi @@ -1315,9 +1265,9 @@ alternatives --add-slave python3 %{_bindir}/python3.8 \ %postun debug # Do this only during uninstall process (not during update) if [ $1 -eq 0 ]; then - alternatives --keep-foreign --remove-slave python3 %{_bindir}/python3.8 \ + alternatives --remove-slave python3 %{_bindir}/python3.8 \ python3-debug - alternatives --keep-foreign --remove-slave python3 %{_bindir}/python3.8 \ + alternatives --remove-slave python3 %{_bindir}/python3.8 \ python3-debug-config fi @@ -1331,7 +1281,7 @@ alternatives --add-slave python3 %{_bindir}/python3.8 \ %postun idle # Do this only during uninstall process (not during update) if [ $1 -eq 0 ]; then - alternatives --keep-foreign --remove-slave python3 %{_bindir}/python3.8 \ + alternatives --remove-slave python3 %{_bindir}/python3.8 \ idle3 fi @@ -1843,61 +1793,6 @@ fi # ====================================================== %changelog -* Wed Aug 09 2023 Petr Viktorin - 3.8.17-2 -- Fix symlink handling in the fix for CVE-2023-24329 -Resolves: rhbz#263261 - -* Mon Aug 07 2023 Charalampos Stratakis - 3.8.17-1 -- Update to 3.8.17 -- Security fix for CVE-2023-24329 -- Add filters for tarfile extraction (CVE-2007-4559, PEP-706) -Resolves: rhbz#2173917, rhbz#263261 - -* Tue Jul 18 2023 Charalampos Stratakis - 3.8.16-2 -- Strip the LTO bytecode from python.o -Resolves: rhbz#2213526 - -* Tue Dec 13 2022 Charalampos Stratakis - 3.8.16-1 -- Update to 3.8.16 -- Security fix for CVE-2022-45061 -Resolves: rhbz#2144072 - -* Mon Sep 12 2022 Charalampos Stratakis - 3.8.14-1 -- Rebase to 3.8.14 -- Security fixes for CVE-2020-10735 and CVE-2021-28861 -Resolves: rhbz#1834423, rhbz#2120642 - -* Tue Jun 14 2022 Charalampos Stratakis - 3.8.13-1 -- Rebase to 3.8.13 -- Security fix for CVE-2015-20107 -- Fix the test suite support for Expat >= 2.4.5 -Resolves: rhbz#2075390 - -* Wed Sep 15 2021 Charalampos Stratakis - 3.8.12-1 -- Update to 3.8.12 -Resolves: rhbz#2004587 - -* Tue Sep 07 2021 Charalampos Stratakis - 3.8.11-1 -- Update to 3.8.11 -- Fix for CVE-2021-3733 and CVE-2021-3737 -Resolves: rhbz#1995234, rhbz#1995162 - -* Mon Aug 02 2021 Tomas Orsava - 3.8.8-4 -- Adjusted the postun scriptlets to enable upgrading to RHEL 9 -- Resolves: rhbz#1933055 - -* Tue Jul 27 2021 Charalampos Stratakis - 3.8.8-3 -- Security fix for CVE-2021-29921: Leading zeros in IPv4 addresses are no longer tolerated -Resolves: rhbz#1957458 - -* Fri Apr 30 2021 Charalampos Stratakis - 3.8.8-2 -- Security fix for CVE-2021-3426: information disclosure via pydoc -Resolves: rhbz#1935913 - -* Mon Mar 15 2021 Lumír Balhar - 3.8.8-1 -- Update to 3.8.8 and fix CVE-2021-23336 -Resolves: rhbz#1928904 - * Fri Jan 22 2021 Charalampos Stratakis - 3.8.6-3 - Security fix for CVE-2021-3177 Resolves: rhbz#1919161