import python3-3.6.8-36.el8

This commit is contained in:
CentOS Sources 2021-03-30 07:58:22 -04:00 committed by Stepan Oksanichenko
parent 60ad1ecf4f
commit b70d3dfde9
9 changed files with 943 additions and 72 deletions

View File

@ -1,58 +0,0 @@
diff -up Python-3.5.0/configure.ac.than Python-3.5.0/configure.ac
--- Python-3.5.0/configure.ac.than 2015-11-13 11:51:32.039560172 -0500
+++ Python-3.5.0/configure.ac 2015-11-13 11:52:11.670168157 -0500
@@ -788,9 +788,9 @@ cat >> conftest.c <<EOF
alpha-linux-gnu
# elif defined(__ARM_EABI__) && defined(__ARM_PCS_VFP)
# if defined(__ARMEL__)
- arm-linux-gnueabihf
+ arm-linux-gnueabi
# else
- armeb-linux-gnueabihf
+ armeb-linux-gnueabi
# endif
# elif defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP)
# if defined(__ARMEL__)
@@ -810,7 +810,7 @@ cat >> conftest.c <<EOF
# elif _MIPS_SIM == _ABIN32
mips64el-linux-gnuabin32
# elif _MIPS_SIM == _ABI64
- mips64el-linux-gnuabi64
+ mips64el-linux-gnu
# else
# error unknown platform triplet
# endif
@@ -820,7 +820,7 @@ cat >> conftest.c <<EOF
# elif _MIPS_SIM == _ABIN32
mips64-linux-gnuabin32
# elif _MIPS_SIM == _ABI64
- mips64-linux-gnuabi64
+ mips64-linux-gnu
# else
# error unknown platform triplet
# endif
@@ -830,9 +830,9 @@ cat >> conftest.c <<EOF
powerpc-linux-gnuspe
# elif defined(__powerpc64__)
# if defined(__LITTLE_ENDIAN__)
- powerpc64le-linux-gnu
+ ppc64le-linux-gnu
# else
- powerpc64-linux-gnu
+ ppc64-linux-gnu
# endif
# elif defined(__powerpc__)
powerpc-linux-gnu
diff --git a/config.sub b/config.sub
index 40ea5df..932128b 100755
--- a/config.sub
+++ b/config.sub
@@ -1045,7 +1045,7 @@ case $basic_machine in
;;
ppc64) basic_machine=powerpc64-unknown
;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppc64le | powerpc64little)
basic_machine=powerpc64le-unknown

View File

@ -0,0 +1,67 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Wed, 15 Jul 2020 05:36:36 -0700
Subject: [PATCH] 00351: Avoid infinite loop in the tarfile module
Avoid infinite loop when reading specially crafted TAR files using the tarfile module
(CVE-2019-20907).
Fixed upstream: https://bugs.python.org/issue39017
---
Lib/tarfile.py | 2 ++
Lib/test/recursion.tar | Bin 0 -> 516 bytes
Lib/test/test_tarfile.py | 7 +++++++
.../2020-07-12-22-16-58.bpo-39017.x3Cg-9.rst | 1 +
4 files changed, 10 insertions(+)
create mode 100644 Lib/test/recursion.tar
create mode 100644 Misc/NEWS.d/next/Library/2020-07-12-22-16-58.bpo-39017.x3Cg-9.rst
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 62d22150f5..2ea47978ff 100755
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -1231,6 +1231,8 @@ class TarInfo(object):
length, keyword = match.groups()
length = int(length)
+ if length == 0:
+ raise InvalidHeaderError("invalid header")
value = buf[match.end(2) + 1:match.start(1) + length - 1]
# Normally, we could just use "utf-8" as the encoding and "strict"
diff --git a/Lib/test/recursion.tar b/Lib/test/recursion.tar
new file mode 100644
index 0000000000000000000000000000000000000000..b8237251964983f54ed1966297e887636cd0c5f4
GIT binary patch
literal 516
zcmYdFPRz+kEn=W0Fn}74P8%Xw3X=l~85kIuo0>8xq$A1Gm}!7)KUsFc41m#O8A5+e
I1_}|j06>QaCIA2c
literal 0
HcmV?d00001
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 4cd7d5370f..573be812ea 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -395,6 +395,13 @@ class CommonReadTest(ReadTest):
with self.assertRaisesRegex(tarfile.ReadError, "unexpected end of data"):
tar.extractfile(t).read()
+ def test_length_zero_header(self):
+ # bpo-39017 (CVE-2019-20907): reading a zero-length header should fail
+ # with an exception
+ with self.assertRaisesRegex(tarfile.ReadError, "file could not be opened successfully"):
+ with tarfile.open(support.findfile('recursion.tar')) as tar:
+ pass
+
class MiscReadTestBase(CommonReadTest):
def requires_name_attribute(self):
pass
diff --git a/Misc/NEWS.d/next/Library/2020-07-12-22-16-58.bpo-39017.x3Cg-9.rst b/Misc/NEWS.d/next/Library/2020-07-12-22-16-58.bpo-39017.x3Cg-9.rst
new file mode 100644
index 0000000000..ad26676f8b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-12-22-16-58.bpo-39017.x3Cg-9.rst
@@ -0,0 +1 @@
+Avoid infinite loop when reading specially crafted TAR files using the tarfile module (CVE-2019-20907).

View File

@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tapas Kundu <39723251+tapakund@users.noreply.github.com>
Date: Wed, 1 Jul 2020 01:00:22 +0530
Subject: [PATCH] 00352: Resolve hash collisions for IPv4Interface and
IPv6Interface
CVE-2020-14422
The hash() methods of classes IPv4Interface and IPv6Interface had issue
of generating constant hash values of 32 and 128 respectively causing hash collisions.
The fix uses the hash() function to generate hash values for the objects
instead of XOR operation.
Fixed upstream: https://bugs.python.org/issue41004
---
Lib/ipaddress.py | 4 ++--
Lib/test/test_ipaddress.py | 11 +++++++++++
.../Security/2020-06-29-16-02-29.bpo-41004.ovF0KZ.rst | 1 +
3 files changed, 14 insertions(+), 2 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2020-06-29-16-02-29.bpo-41004.ovF0KZ.rst
diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py
index 583f02ad54..98492136ca 100644
--- a/Lib/ipaddress.py
+++ b/Lib/ipaddress.py
@@ -1418,7 +1418,7 @@ class IPv4Interface(IPv4Address):
return False
def __hash__(self):
- return self._ip ^ self._prefixlen ^ int(self.network.network_address)
+ return hash((self._ip, self._prefixlen, int(self.network.network_address)))
__reduce__ = _IPAddressBase.__reduce__
@@ -2092,7 +2092,7 @@ class IPv6Interface(IPv6Address):
return False
def __hash__(self):
- return self._ip ^ self._prefixlen ^ int(self.network.network_address)
+ return hash((self._ip, self._prefixlen, int(self.network.network_address)))
__reduce__ = _IPAddressBase.__reduce__
diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py
index 1cef4217bc..7de444af4a 100644
--- a/Lib/test/test_ipaddress.py
+++ b/Lib/test/test_ipaddress.py
@@ -1990,6 +1990,17 @@ class IpaddrUnitTest(unittest.TestCase):
sixtofouraddr.sixtofour)
self.assertFalse(bad_addr.sixtofour)
+ # issue41004 Hash collisions in IPv4Interface and IPv6Interface
+ def testV4HashIsNotConstant(self):
+ ipv4_address1 = ipaddress.IPv4Interface("1.2.3.4")
+ ipv4_address2 = ipaddress.IPv4Interface("2.3.4.5")
+ self.assertNotEqual(ipv4_address1.__hash__(), ipv4_address2.__hash__())
+
+ # issue41004 Hash collisions in IPv4Interface and IPv6Interface
+ def testV6HashIsNotConstant(self):
+ ipv6_address1 = ipaddress.IPv6Interface("2001:658:22a:cafe:200:0:0:1")
+ ipv6_address2 = ipaddress.IPv6Interface("2001:658:22a:cafe:200:0:0:2")
+ self.assertNotEqual(ipv6_address1.__hash__(), ipv6_address2.__hash__())
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS.d/next/Security/2020-06-29-16-02-29.bpo-41004.ovF0KZ.rst b/Misc/NEWS.d/next/Security/2020-06-29-16-02-29.bpo-41004.ovF0KZ.rst
new file mode 100644
index 0000000000..f5a9db52ff
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2020-06-29-16-02-29.bpo-41004.ovF0KZ.rst
@@ -0,0 +1 @@
+CVE-2020-14422: The __hash__() methods of ipaddress.IPv4Interface and ipaddress.IPv6Interface incorrectly generated constant hash values of 32 and 128 respectively. This resulted in always causing hash collisions. The fix uses hash() to generate hash values for the tuple of (address, mask length, network address).

View File

@ -0,0 +1,97 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 4 Aug 2020 12:04:03 +0200
Subject: [PATCH] 00353: Original names for architectures with different names
downstream
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://fedoraproject.org/wiki/Changes/Python_Upstream_Architecture_Names
Pythons in RHEL/Fedora used different names for some architectures
than upstream and other distros (for example ppc64 vs. powerpc64).
This was patched in patch 274, now it is sedded if %with legacy_archnames.
That meant that an extension built with the default upstream settings
(on other distro or as an manylinux wheel) could not been found by Python
on RHEL/Fedora because it had a different suffix.
This patch adds the legacy names to importlib so Python is able
to import extensions with a legacy architecture name in its
file name.
It work both ways, so it support both %with and %without legacy_archnames.
WARNING: This patch has no effect on Python built with bootstrap
enabled because Python/importlib_external.h is not regenerated
and therefore Python during bootstrap contains importlib from
upstream without this feature. It's possible to include
Python/importlib_external.h to this patch but it'd make rebasing
a nightmare because it's basically a binary file.
Co-authored-by: Miro Hrončok <miro@hroncok.cz>
---
Lib/importlib/_bootstrap_external.py | 40 ++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 9feec50842..5bb2454a5c 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -1361,7 +1361,7 @@ def _get_supported_file_loaders():
Each item is a tuple (loader, suffixes).
"""
- extensions = ExtensionFileLoader, _imp.extension_suffixes()
+ extensions = ExtensionFileLoader, _alternative_architectures(_imp.extension_suffixes())
source = SourceFileLoader, SOURCE_SUFFIXES
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
return [extensions, source, bytecode]
@@ -1428,7 +1428,7 @@ def _setup(_bootstrap_module):
# Constants
setattr(self_module, '_relax_case', _make_relax_case())
- EXTENSION_SUFFIXES.extend(_imp.extension_suffixes())
+ EXTENSION_SUFFIXES.extend(_alternative_architectures(_imp.extension_suffixes()))
if builtin_os == 'nt':
SOURCE_SUFFIXES.append('.pyw')
if '_d.pyd' in EXTENSION_SUFFIXES:
@@ -1441,3 +1441,39 @@ def _install(_bootstrap_module):
supported_loaders = _get_supported_file_loaders()
sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
sys.meta_path.append(PathFinder)
+
+
+_ARCH_MAP = {
+ "-arm-linux-gnueabi.": "-arm-linux-gnueabihf.",
+ "-armeb-linux-gnueabi.": "-armeb-linux-gnueabihf.",
+ "-mips64-linux-gnu.": "-mips64-linux-gnuabi64.",
+ "-mips64el-linux-gnu.": "-mips64el-linux-gnuabi64.",
+ "-ppc-linux-gnu.": "-powerpc-linux-gnu.",
+ "-ppc-linux-gnuspe.": "-powerpc-linux-gnuspe.",
+ "-ppc64-linux-gnu.": "-powerpc64-linux-gnu.",
+ "-ppc64le-linux-gnu.": "-powerpc64le-linux-gnu.",
+ # The above, but the other way around:
+ "-arm-linux-gnueabihf.": "-arm-linux-gnueabi.",
+ "-armeb-linux-gnueabihf.": "-armeb-linux-gnueabi.",
+ "-mips64-linux-gnuabi64.": "-mips64-linux-gnu.",
+ "-mips64el-linux-gnuabi64.": "-mips64el-linux-gnu.",
+ "-powerpc-linux-gnu.": "-ppc-linux-gnu.",
+ "-powerpc-linux-gnuspe.": "-ppc-linux-gnuspe.",
+ "-powerpc64-linux-gnu.": "-ppc64-linux-gnu.",
+ "-powerpc64le-linux-gnu.": "-ppc64le-linux-gnu.",
+}
+
+
+def _alternative_architectures(suffixes):
+ """Add a suffix with an alternative architecture name
+ to the list of suffixes so an extension built with
+ the default (upstream) setting is loadable with our Pythons
+ """
+
+ for suffix in suffixes:
+ for original, alternative in _ARCH_MAP.items():
+ if original in suffix:
+ suffixes.append(suffix.replace(original, alternative))
+ return suffixes
+
+ return suffixes

View File

@ -0,0 +1,73 @@
diff --git a/Lib/http/client.py b/Lib/http/client.py
index f0d2642..0a044e9 100644
--- a/Lib/http/client.py
+++ b/Lib/http/client.py
@@ -151,6 +151,10 @@ _contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f]')
# _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$")
# We are more lenient for assumed real world compatibility purposes.
+# These characters are not allowed within HTTP method names
+# to prevent http header injection.
+_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]')
+
# We always set the Content-Length header for these methods because some
# servers will otherwise respond with a 411
_METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'}
@@ -1117,6 +1121,8 @@ class HTTPConnection:
else:
raise CannotSendRequest(self.__state)
+ self._validate_method(method)
+
# Save the method we use, we need it later in the response phase
self._method = method
if not url:
@@ -1207,6 +1213,15 @@ class HTTPConnection:
# For HTTP/1.0, the server will assume "not chunked"
pass
+ def _validate_method(self, method):
+ """Validate a method name for putrequest."""
+ # prevent http header injection
+ match = _contains_disallowed_method_pchar_re.search(method)
+ if match:
+ raise ValueError(
+ f"method can't contain control characters. {method!r} "
+ f"(found at least {match.group()!r})")
+
def putheader(self, header, *values):
"""Send a request header line to the server.
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 5795b7a..af0350f 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -359,6 +359,28 @@ class HeaderTests(TestCase):
self.assertEqual(lines[2], "header: Second: val")
+class HttpMethodTests(TestCase):
+ def test_invalid_method_names(self):
+ methods = (
+ 'GET\r',
+ 'POST\n',
+ 'PUT\n\r',
+ 'POST\nValue',
+ 'POST\nHOST:abc',
+ 'GET\nrHost:abc\n',
+ 'POST\rRemainder:\r',
+ 'GET\rHOST:\n',
+ '\nPUT'
+ )
+
+ for method in methods:
+ with self.assertRaisesRegex(
+ ValueError, "method can't contain control characters"):
+ conn = client.HTTPConnection('example.com')
+ conn.sock = FakeSocket(None)
+ conn.request(method=method, url="/")
+
+
class TransferEncodingTest(TestCase):
expected_body = b"It's just a flesh wound"

View File

@ -0,0 +1,42 @@
diff --git a/Lib/test/multibytecodec_support.py b/Lib/test/multibytecodec_support.py
index f9884c6..98feec2 100644
--- a/Lib/test/multibytecodec_support.py
+++ b/Lib/test/multibytecodec_support.py
@@ -300,29 +300,23 @@ class TestBase_Mapping(unittest.TestCase):
self._test_mapping_file_plain()
def _test_mapping_file_plain(self):
- unichrs = lambda s: ''.join(map(chr, map(eval, s.split('+'))))
+ def unichrs(s):
+ return ''.join(chr(int(x, 16)) for x in s.split('+'))
+
urt_wa = {}
with self.open_mapping_file() as f:
for line in f:
if not line:
break
- data = line.split('#')[0].strip().split()
+ data = line.split('#')[0].split()
if len(data) != 2:
continue
- csetval = eval(data[0])
- if csetval <= 0x7F:
- csetch = bytes([csetval & 0xff])
- elif csetval >= 0x1000000:
- csetch = bytes([(csetval >> 24), ((csetval >> 16) & 0xff),
- ((csetval >> 8) & 0xff), (csetval & 0xff)])
- elif csetval >= 0x10000:
- csetch = bytes([(csetval >> 16), ((csetval >> 8) & 0xff),
- (csetval & 0xff)])
- elif csetval >= 0x100:
- csetch = bytes([(csetval >> 8), (csetval & 0xff)])
- else:
+ if data[0][:2] != '0x':
+ self.fail(f"Invalid line: {line!r}")
+ csetch = bytes.fromhex(data[0][2:])
+ if len(csetch) == 1 and 0x80 <= csetch[0]:
continue
unich = unichrs(data[1])

View File

@ -0,0 +1,269 @@
From 0cfd9a7f26488567b9a3e5ec192099a8b80ad9df Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
Date: Tue, 19 Jan 2021 07:55:37 +0100
Subject: [PATCH] [PATCH] bpo-37064: Add -k and -a options to pathfix.py tool
(GH-16387)
* bpo-37064: Add option -k to Tools/scripts/pathfix.py (GH-15548)
Add flag -k to pathscript.py script: preserve shebang flags.
(cherry picked from commit 50254ac4c179cb412e90682098c97db786143929)
* bpo-37064: Add option -a to pathfix.py tool (GH-15717)
Add option -a to Tools/Scripts/pathfix.py script: add flags.
(cherry picked from commit 1dc1acbd73f05f14c974b7ce1041787d7abef31e)
---
Lib/test/test_tools/test_pathfix.py | 104 ++++++++++++++++++++++++++++
Tools/scripts/pathfix.py | 64 +++++++++++++++--
2 files changed, 163 insertions(+), 5 deletions(-)
create mode 100644 Lib/test/test_tools/test_pathfix.py
diff --git a/Lib/test/test_tools/test_pathfix.py b/Lib/test/test_tools/test_pathfix.py
new file mode 100644
index 0000000..1f0585e
--- /dev/null
+++ b/Lib/test/test_tools/test_pathfix.py
@@ -0,0 +1,104 @@
+import os
+import subprocess
+import sys
+import unittest
+from test import support
+from test.test_tools import import_tool, scriptsdir
+
+
+class TestPathfixFunctional(unittest.TestCase):
+ script = os.path.join(scriptsdir, 'pathfix.py')
+
+ def setUp(self):
+ self.temp_file = support.TESTFN
+ self.addCleanup(support.unlink, support.TESTFN)
+
+ def pathfix(self, shebang, pathfix_flags, exitcode=0, stdout='', stderr=''):
+ with open(self.temp_file, 'w', encoding='utf8') as f:
+ f.write(f'{shebang}\n' + 'print("Hello world")\n')
+
+ proc = subprocess.run(
+ [sys.executable, self.script,
+ *pathfix_flags, '-n', self.temp_file],
+ universal_newlines=True, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ if stdout == '' and proc.returncode == 0:
+ stdout = f'{self.temp_file}: updating\n'
+ self.assertEqual(proc.returncode, exitcode, proc)
+ self.assertEqual(proc.stdout, stdout, proc)
+ self.assertEqual(proc.stderr, stderr, proc)
+
+ with open(self.temp_file, 'r', encoding='utf8') as f:
+ output = f.read()
+
+ lines = output.split('\n')
+ self.assertEqual(lines[1:], ['print("Hello world")', ''])
+ new_shebang = lines[0]
+
+ if proc.returncode != 0:
+ self.assertEqual(shebang, new_shebang)
+
+ return new_shebang
+
+ def test_pathfix(self):
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python',
+ ['-i', '/usr/bin/python3']),
+ '#! /usr/bin/python3')
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python -R',
+ ['-i', '/usr/bin/python3']),
+ '#! /usr/bin/python3')
+
+ def test_pathfix_keeping_flags(self):
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python -R',
+ ['-i', '/usr/bin/python3', '-k']),
+ '#! /usr/bin/python3 -R')
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python',
+ ['-i', '/usr/bin/python3', '-k']),
+ '#! /usr/bin/python3')
+
+ def test_pathfix_adding_flag(self):
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python',
+ ['-i', '/usr/bin/python3', '-a', 's']),
+ '#! /usr/bin/python3 -s')
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python -S',
+ ['-i', '/usr/bin/python3', '-a', 's']),
+ '#! /usr/bin/python3 -s')
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python -V',
+ ['-i', '/usr/bin/python3', '-a', 'v', '-k']),
+ '#! /usr/bin/python3 -vV')
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python',
+ ['-i', '/usr/bin/python3', '-a', 'Rs']),
+ '#! /usr/bin/python3 -Rs')
+ self.assertEqual(
+ self.pathfix(
+ '#! /usr/bin/env python -W default',
+ ['-i', '/usr/bin/python3', '-a', 's', '-k']),
+ '#! /usr/bin/python3 -sW default')
+
+ def test_pathfix_adding_errors(self):
+ self.pathfix(
+ '#! /usr/bin/env python -E',
+ ['-i', '/usr/bin/python3', '-a', 'W default', '-k'],
+ exitcode=2,
+ stderr="-a option doesn't support whitespaces")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Tools/scripts/pathfix.py b/Tools/scripts/pathfix.py
index c5bf984..2dfa6e8 100755
--- a/Tools/scripts/pathfix.py
+++ b/Tools/scripts/pathfix.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Change the #! line occurring in Python scripts. The new interpreter
+# Change the #! line (shebang) occurring in Python scripts. The new interpreter
# pathname must be given with a -i option.
#
# Command line arguments are files or directories to be processed.
@@ -10,7 +10,13 @@
# arguments).
# The original file is kept as a back-up (with a "~" attached to its name),
# -n flag can be used to disable this.
-#
+
+# Sometimes you may find shebangs with flags such as `#! /usr/bin/env python -si`.
+# Normally, pathfix overwrites the entire line, including the flags.
+# To change interpreter and keep flags from the original shebang line, use -k.
+# If you want to keep flags and add to them one single literal flag, use option -a.
+
+
# Undoubtedly you can do this using find and sed or perl, but this is
# a nice example of Python code that recurses down a directory tree
# and uses regular expressions. Also note several subtleties like
@@ -33,16 +39,21 @@ rep = sys.stdout.write
new_interpreter = None
preserve_timestamps = False
create_backup = True
+keep_flags = False
+add_flags = b''
def main():
global new_interpreter
global preserve_timestamps
global create_backup
- usage = ('usage: %s -i /interpreter -p -n file-or-directory ...\n' %
+ global keep_flags
+ global add_flags
+
+ usage = ('usage: %s -i /interpreter -p -n -k -a file-or-directory ...\n' %
sys.argv[0])
try:
- opts, args = getopt.getopt(sys.argv[1:], 'i:pn')
+ opts, args = getopt.getopt(sys.argv[1:], 'i:a:kpn')
except getopt.error as msg:
err(str(msg) + '\n')
err(usage)
@@ -54,6 +65,13 @@ def main():
preserve_timestamps = True
if o == '-n':
create_backup = False
+ if o == '-k':
+ keep_flags = True
+ if o == '-a':
+ add_flags = a.encode()
+ if b' ' in add_flags:
+ err("-a option doesn't support whitespaces")
+ sys.exit(2)
if not new_interpreter or not new_interpreter.startswith(b'/') or \
not args:
err('-i option or file-or-directory missing\n')
@@ -70,10 +88,14 @@ def main():
if fix(arg): bad = 1
sys.exit(bad)
+
ispythonprog = re.compile(r'^[a-zA-Z0-9_]+\.py$')
+
+
def ispython(name):
return bool(ispythonprog.match(name))
+
def recursedown(dirname):
dbg('recursedown(%r)\n' % (dirname,))
bad = 0
@@ -96,6 +118,7 @@ def recursedown(dirname):
if recursedown(fullname): bad = 1
return bad
+
def fix(filename):
## dbg('fix(%r)\n' % (filename,))
try:
@@ -166,12 +189,43 @@ def fix(filename):
# Return success
return 0
+
+def parse_shebang(shebangline):
+ shebangline = shebangline.rstrip(b'\n')
+ start = shebangline.find(b' -')
+ if start == -1:
+ return b''
+ return shebangline[start:]
+
+
+def populate_flags(shebangline):
+ old_flags = b''
+ if keep_flags:
+ old_flags = parse_shebang(shebangline)
+ if old_flags:
+ old_flags = old_flags[2:]
+ if not (old_flags or add_flags):
+ return b''
+ # On Linux, the entire string following the interpreter name
+ # is passed as a single argument to the interpreter.
+ # e.g. "#! /usr/bin/python3 -W Error -s" runs "/usr/bin/python3 "-W Error -s"
+ # so shebang should have single '-' where flags are given and
+ # flag might need argument for that reasons adding new flags is
+ # between '-' and original flags
+ # e.g. #! /usr/bin/python3 -sW Error
+ return b' -' + add_flags + old_flags
+
+
def fixline(line):
if not line.startswith(b'#!'):
return line
+
if b"python" not in line:
return line
- return b'#! ' + new_interpreter + b'\n'
+
+ flags = populate_flags(line)
+ return b'#! ' + new_interpreter + flags + b'\n'
+
if __name__ == '__main__':
main()
--
2.29.2

View File

@ -0,0 +1,184 @@
From e92381a0a6a3e1f000956e1f1e70e543b9c2bcd5 Mon Sep 17 00:00:00 2001
From: Benjamin Peterson <benjamin@python.org>
Date: Mon, 18 Jan 2021 14:47:05 -0600
Subject: [PATCH] [3.6] closes bpo-42938: Replace snprintf with Python unicode
formatting in ctypes param reprs. (24239). (cherry picked from commit
916610ef90a0d0761f08747f7b0905541f0977c7)
Co-authored-by: Benjamin Peterson <benjamin@python.org>
---
Lib/ctypes/test/test_parameters.py | 43 +++++++++++++++
.../2021-01-18-09-27-31.bpo-42938.4Zn4Mp.rst | 2 +
Modules/_ctypes/callproc.c | 55 +++++++------------
3 files changed, 66 insertions(+), 34 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"^<cparam '\?' at 0x[A-Fa-f0-9]+>$")
+ self.assertEqual(repr(c_char.from_param(97)), "<cparam 'c' ('a')>")
+ self.assertRegex(repr(c_wchar.from_param('a')), r"^<cparam 'u' at 0x[A-Fa-f0-9]+>$")
+ self.assertEqual(repr(c_byte.from_param(98)), "<cparam 'b' (98)>")
+ self.assertEqual(repr(c_ubyte.from_param(98)), "<cparam 'B' (98)>")
+ self.assertEqual(repr(c_short.from_param(511)), "<cparam 'h' (511)>")
+ self.assertEqual(repr(c_ushort.from_param(511)), "<cparam 'H' (511)>")
+ self.assertRegex(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
+ self.assertRegex(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
+ self.assertRegex(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
+ self.assertRegex(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
+ self.assertRegex(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$")
+ self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^<cparam '[LIQ]' \(20000\)>$")
+ self.assertEqual(repr(c_float.from_param(1.5)), "<cparam 'f' (1.5)>")
+ self.assertEqual(repr(c_double.from_param(1.5)), "<cparam 'd' (1.5)>")
+ self.assertEqual(repr(c_double.from_param(1e300)), "<cparam 'd' (1e+300)>")
+ self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$")
+ self.assertRegex(repr(c_char_p.from_param(b'hihi')), "^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$")
+ self.assertRegex(repr(c_wchar_p.from_param('hihi')), "^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$")
+ self.assertRegex(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$")
+
################################################################
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 d1c190f359108..2bb289bce043f 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -461,58 +461,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, "<cparam '%c' (%d)>",
+ return PyUnicode_FromFormat("<cparam '%c' (%d)>",
self->tag, self->value.b);
- break;
case 'h':
case 'H':
- sprintf(buffer, "<cparam '%c' (%d)>",
+ return PyUnicode_FromFormat("<cparam '%c' (%d)>",
self->tag, self->value.h);
- break;
case 'i':
case 'I':
- sprintf(buffer, "<cparam '%c' (%d)>",
+ return PyUnicode_FromFormat("<cparam '%c' (%d)>",
self->tag, self->value.i);
- break;
case 'l':
case 'L':
- sprintf(buffer, "<cparam '%c' (%ld)>",
+ return PyUnicode_FromFormat("<cparam '%c' (%ld)>",
self->tag, self->value.l);
- break;
case 'q':
case 'Q':
- sprintf(buffer,
-#ifdef MS_WIN32
- "<cparam '%c' (%I64d)>",
-#else
- "<cparam '%c' (%lld)>",
-#endif
+ return PyUnicode_FromFormat("<cparam '%c' (%lld)>",
self->tag, self->value.q);
- break;
case 'd':
- sprintf(buffer, "<cparam '%c' (%f)>",
- self->tag, self->value.d);
- break;
- case 'f':
- sprintf(buffer, "<cparam '%c' (%f)>",
- 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("<cparam '%c' (%R)>", self->tag, f);
+ Py_DECREF(f);
+ return result;
+ }
case 'c':
if (is_literal_char((unsigned char)self->value.c)) {
- sprintf(buffer, "<cparam '%c' ('%c')>",
+ return PyUnicode_FromFormat("<cparam '%c' ('%c')>",
self->tag, self->value.c);
}
else {
- sprintf(buffer, "<cparam '%c' ('\\x%02x')>",
+ return PyUnicode_FromFormat("<cparam '%c' ('\\x%02x')>",
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
@@ -521,22 +510,20 @@ PyCArg_repr(PyCArgObject *self)
case 'z':
case 'Z':
case 'P':
- sprintf(buffer, "<cparam '%c' (%p)>",
+ return PyUnicode_FromFormat("<cparam '%c' (%p)>",
self->tag, self->value.p);
break;
default:
if (is_literal_char((unsigned char)self->tag)) {
- sprintf(buffer, "<cparam '%c' at %p>",
- (unsigned char)self->tag, self);
+ return PyUnicode_FromFormat("<cparam '%c' at %p>",
+ (unsigned char)self->tag, (void *)self);
}
else {
- sprintf(buffer, "<cparam 0x%02x at %p>",
- (unsigned char)self->tag, self);
+ return PyUnicode_FromFormat("<cparam 0x%02x at %p>",
+ (unsigned char)self->tag, (void *)self);
}
- break;
}
- return PyUnicode_FromString(buffer);
}
static PyMemberDef PyCArgType_members[] = {

View File

@ -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
Version: %{pybasever}.8
Release: 30%{?dist}
Release: 36%{?dist}
License: Python
@ -56,6 +56,15 @@ License: Python
%bcond_with valgrind
%endif
# https://fedoraproject.org/wiki/Changes/Python_Upstream_Architecture_Names
# For a very long time we have converted "upstream architecture names" to "Fedora names".
# This made sense at the time, see https://github.com/pypa/manylinux/issues/687#issuecomment-666362947
# However, with manylinux wheels popularity growth, this is now a problem.
# Wheels built on a Linux that doesn't do this were not compatible with ours and vice versa.
# We now have a compatibility layer to workaround a problem,
# but we also no longer use the legacy arch names in Fedora 34+.
# This bcond controls the behavior. The defaults should be good for anybody.
%bcond_without legacy_archnames
# ==================================
# Notes from bootstraping Python 3.6
@ -111,8 +120,21 @@ License: Python
%global LDVERSION_optimized %{pybasever}%{ABIFLAGS_optimized}
%global LDVERSION_debug %{pybasever}%{ABIFLAGS_debug}
%global SOABI_optimized cpython-%{pyshortver}%{ABIFLAGS_optimized}-%{_arch}-linux%{_gnu}
%global SOABI_debug cpython-%{pyshortver}%{ABIFLAGS_debug}-%{_arch}-linux%{_gnu}
# When we use the upstream arch triplets, we convert them from the legacy ones
# This is reversed in prep when %%with legacy_archnames, so we keep both macros
%global platform_triplet_legacy %{_arch}-linux%{_gnu}
%global platform_triplet_upstream %{expand:%(echo %{platform_triplet_legacy} | sed -E \\
-e 's/^arm(eb)?-linux-gnueabi$/arm\\1-linux-gnueabihf/' \\
-e 's/^mips64(el)?-linux-gnu$/mips64\\1-linux-gnuabi64/' \\
-e 's/^ppc(64)?(le)?-linux-gnu$/powerpc\\1\\2-linux-gnu/')}
%if %{with legacy_archnames}
%global platform_triplet %{platform_triplet_legacy}
%else
%global platform_triplet %{platform_triplet_upstream}
%endif
%global SOABI_optimized cpython-%{pyshortver}%{ABIFLAGS_optimized}-%{platform_triplet}
%global SOABI_debug cpython-%{pyshortver}%{ABIFLAGS_debug}-%{platform_triplet}
# All bytecode files are in a __pycache__ subdirectory, with a name
# reflecting the version of the bytecode.
@ -170,6 +192,7 @@ BuildRequires: gcc-c++
%if %{with gdbm}
BuildRequires: gdbm-devel >= 1:1.13
%endif
BuildRequires: git-core
BuildRequires: glibc-devel
BuildRequires: gmp-devel
BuildRequires: libappstream-glib
@ -328,10 +351,6 @@ Patch251: 00251-change-user-install-location.patch
# Original proposal: https://bugzilla.redhat.com/show_bug.cgi?id=1404918
Patch262: 00262-pep538_coerce_legacy_c_locale.patch
# 00274 #
# Upstream uses Debian-style architecture naming. Change to match Fedora.
Patch274: 00274-fix-arch-names.patch
# 00294 #
# Define TLS cipher suite on build time depending
# on the OpenSSL default cipher suite selection.
@ -501,6 +520,70 @@ Patch345: 00345-fix-test_site-with-extra-pth-files.patch
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1810618
Patch346: 00346-CVE-2020-8492.patch
# 00351 #
# Avoid infinite loop when reading specially crafted TAR files using the tarfile module
# (CVE-2019-20907).
# See: https://bugs.python.org/issue39017
Patch351: 00351-avoid-infinite-loop-in-the-tarfile-module.patch
# 00352 # 5253c417a23b3658fa115d2c72fa54b20293a31c
# Resolve hash collisions for IPv4Interface and IPv6Interface
#
# CVE-2020-14422
# The hash() methods of classes IPv4Interface and IPv6Interface had issue
# of generating constant hash values of 32 and 128 respectively causing hash collisions.
# The fix uses the hash() function to generate hash values for the objects
# instead of XOR operation.
# Fixed upstream: https://bugs.python.org/issue41004
Patch352: 00352-resolve-hash-collisions-for-ipv4interface-and-ipv6interface.patch
# 00353 #
# Original names for architectures with different names downstream
#
# https://fedoraproject.org/wiki/Changes/Python_Upstream_Architecture_Names
#
# Pythons in RHEL/Fedora used different names for some architectures
# than upstream and other distros (for example ppc64 vs. powerpc64).
# This was patched in patch 274, now it is sedded if %%with legacy_archnames.
#
# That meant that an extension built with the default upstream settings
# (on other distro or as an manylinux wheel) could not been found by Python
# on RHEL/Fedora because it had a different suffix.
# This patch adds the legacy names to importlib so Python is able
# to import extensions with a legacy architecture name in its
# file name.
# It work both ways, so it support both %%with and %%without legacy_archnames.
#
# WARNING: This patch has no effect on Python built with bootstrap
# enabled because Python/importlib_external.h is not regenerated
# and therefore Python during bootstrap contains importlib from
# upstream without this feature. It's possible to include
# Python/importlib_external.h to this patch but it'd make rebasing
# a nightmare because it's basically a binary file.
Patch353: 00353-architecture-names-upstream-downstream.patch
# 00354 #
# Reject control chars in HTTP method in http.client to prevent
# HTTP header injection
# Fixed ustream: https://bugs.python.org/issue39603
Patch354: 00354-cve-2020-26116-http-request-method-crlf-injection-in-httplib.patch
# 00355 #
# No longer call eval() on content received via HTTP in the CJK codec tests
# Fixed upstream: https://bugs.python.org/issue41944
Patch355: 00355-CVE-2020-27619.patch
# 00356 #
# options -a and -k for pathfix.py used in %%py3_shebang_fix
# Upstream: https://github.com/python/cpython/commit/c71c54c62600fd721baed3c96709e3d6e9c33817
Patch356: 00356-k_and_a_options_for_pathfix.patch
# 00357 #
# CVE-2021-3177 stack-based buffer overflow in PyCArg_repr in _ctypes/callproc.c
# Upstream: https://bugs.python.org/issue42938
# Main BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1918168
Patch357: 00357-CVE-2021-3177.patch
# (New patches go here ^^^)
#
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
@ -799,7 +882,6 @@ rm Lib/ensurepip/_bundled/*.whl
%patch251 -p1
%patch262 -p1
%patch274 -p1
%patch294 -p1
%patch316 -p1
%patch317 -p1
@ -819,11 +901,26 @@ rm Lib/ensurepip/_bundled/*.whl
%patch345 -p1
%patch346 -p1
# Patch 351 adds binary file for testing. We need to apply it using Git.
git apply %{PATCH351}
%patch352 -p1
%patch353 -p1
%patch354 -p1
%patch355 -p1
%patch356 -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)
rm configure pyconfig.h.in
# When we use the legacy arch names, we need to change them in configure.ac
%if %{with legacy_archnames}
sed -i configure.ac \
-e 's/\b%{platform_triplet_upstream}\b/%{platform_triplet_legacy}/'
%endif
# ======================================================
# Configuring and building the code:
@ -904,6 +1001,9 @@ BuildPython() {
$ExtraConfigArgs \
%{nil}
# Regenerate generated importlib frozen modules (see patch 353)
%make_build CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags" regen-importlib
# Invoke the build
%make_build CFLAGS_NODIST="$CFLAGS_NODIST $MoreCFlags"
@ -1103,7 +1203,7 @@ do
LD_LIBRARY_PATH=./build/optimized ./build/optimized/python \
Tools/scripts/pathfix.py \
-i "%{_libexecdir}/platform-python${LDVersion}" -pn \
%{buildroot}%{pylibdir}/config-${LDVersion}-%{_arch}-linux%{_gnu}/python-config.py
%{buildroot}%{pylibdir}/config-${LDVersion}-%{platform_triplet}/python-config.py
done
# Remove tests for python3-tools which was removed in
@ -1523,8 +1623,8 @@ fi
# "Makefile" and the config-32/64.h file are needed by
# distutils/sysconfig.py:_init_posix(), so we include them in the core
# package, along with their parent directories (bug 531901):
%dir %{pylibdir}/config-%{LDVERSION_optimized}-%{_arch}-linux%{_gnu}/
%{pylibdir}/config-%{LDVERSION_optimized}-%{_arch}-linux%{_gnu}/Makefile
%dir %{pylibdir}/config-%{LDVERSION_optimized}-%{platform_triplet}/
%{pylibdir}/config-%{LDVERSION_optimized}-%{platform_triplet}/Makefile
%dir %{_includedir}/python%{LDVERSION_optimized}/
%{_includedir}/python%{LDVERSION_optimized}/%{_pyconfig_h}
@ -1538,8 +1638,8 @@ fi
%{_bindir}/2to3
# TODO: Remove 2to3-3.7 once rebased to 3.7
%{_bindir}/2to3-%{pybasever}
%{pylibdir}/config-%{LDVERSION_optimized}-%{_arch}-linux%{_gnu}/*
%exclude %{pylibdir}/config-%{LDVERSION_optimized}-%{_arch}-linux%{_gnu}/Makefile
%{pylibdir}/config-%{LDVERSION_optimized}-%{platform_triplet}/*
%exclude %{pylibdir}/config-%{LDVERSION_optimized}-%{platform_triplet}/Makefile
%exclude %{pylibdir}/distutils/command/wininst-*.exe
%{_includedir}/python%{LDVERSION_optimized}/*.h
%exclude %{_includedir}/python%{LDVERSION_optimized}/%{_pyconfig_h}
@ -1687,7 +1787,7 @@ fi
%{_libdir}/%{py_INSTSONAME_debug}
# Analog of the -devel subpackage's files:
%{pylibdir}/config-%{LDVERSION_debug}-%{_arch}-linux%{_gnu}
%{pylibdir}/config-%{LDVERSION_debug}-%{platform_triplet}
%{_includedir}/python%{LDVERSION_debug}
%exclude %{_bindir}/python%{LDVERSION_debug}-config
@ -1735,6 +1835,33 @@ fi
# ======================================================
%changelog
* Fri Jan 22 2021 Lumír Balhar <lbalhar@redhat.com> - 3.6.8-36
- Fix for CVE-2021-3177
Resolves: rhbz#1918168
* Mon Jan 18 2021 Lumír Balhar <lbalhar@redhat.com> - 3.6.8-35
- New options -a and -k for pathfix.py script backported from upstream
Resolves: rhbz#1917691
* Fri Dec 04 2020 Charalampos Stratakis <cstratak@redhat.com> - 3.6.8-34
- Security fix for CVE-2020-27619: eval() call on content received via HTTP in the CJK codec tests
Resolves: rhbz#1890237
* Tue Nov 24 2020 Lumír Balhar <lbalhar@redhat.com> - 3.6.8-33
- Add support for upstream architecture names
https://fedoraproject.org/wiki/Changes/Python_Upstream_Architecture_Names
Resolves: rhbz#1868003
* Mon Nov 09 2020 Charalampos Stratakis <cstratak@redhat.com> - 3.6.8-32
- Security fix for CVE-2020-26116: Reject control chars in HTTP method in http.client
Resolves: rhbz#1883257
* Mon Aug 17 2020 Tomas Orsava <torsava@redhat.com> - 3.6.8-31
- Avoid infinite loop when reading specially crafted TAR files (CVE-2019-20907)
Resolves: rhbz#1856481
- Resolve hash collisions for Pv4Interface and IPv6Interface (CVE-2020-14422)
Resolves: rhbz#1854926
* Thu Jun 25 2020 Victor Stinner <vstinner@python.org> - 3.6.8-30
- Remove downstream 00178-dont-duplicate-flags-in-sysconfig.patch which
introduced a bug on distutils.sysconfig.get_config_var('LIBPL')