An interpreted, interactive, object-oriented programming language
CentOS Sources
2018-10-30 28b2615b3729ec8fe8697be6aeef7928dcb3f394
import python-2.7.5-76.el7
1 files modified
5 files added
370 ■■■■■ changed files
SOURCES/00285-fix-non-deterministic-read-in-test_pty.patch 59 ●●●●● patch | view | raw | blame | history
SOURCES/00298-do-not-send-IP-in-SNI-TLS-extension.patch 60 ●●●●● patch | view | raw | blame | history
SOURCES/00299-fix-ssl-module-pymax.patch 24 ●●●●● patch | view | raw | blame | history
SOURCES/00303-CVE-2018-1060-1.patch 86 ●●●●● patch | view | raw | blame | history
SOURCES/00306-fix-oserror-17-upon-semaphores-creation.patch 44 ●●●●● patch | view | raw | blame | history
SPECS/python.spec 97 ●●●●● patch | view | raw | blame | history
SOURCES/00285-fix-non-deterministic-read-in-test_pty.patch
New file
@@ -0,0 +1,59 @@
diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py
index bec38c45456..f623aa09620 100644
--- a/Lib/test/test_pty.py
+++ b/Lib/test/test_pty.py
@@ -11,6 +11,7 @@
 import select
 import signal
 import socket
+import io # readline
 import unittest
 TEST_STRING_1 = "I wish to buy a fish license.\n"
@@ -24,6 +25,16 @@ def debug(msg):
         pass
+# Note that os.read() is nondeterministic so we need to be very careful
+# to make the test suite deterministic.  A normal call to os.read() may
+# give us less than expected.
+#
+# Beware, on my Linux system, if I put 'foo\n' into a terminal fd, I get
+# back 'foo\r\n' at the other end.  The behavior depends on the termios
+# setting.  The newline translation may be OS-specific.  To make the
+# test suite deterministic and OS-independent, the functions _readline
+# and normalize_output can be used.
+
 def normalize_output(data):
     # Some operating systems do conversions on newline.  We could possibly
     # fix that by doing the appropriate termios.tcsetattr()s.  I couldn't
@@ -45,6 +56,12 @@ def normalize_output(data):
     return data
+def _readline(fd):
+    """Read one line.  May block forever if no newline is read."""
+    reader = io.FileIO(fd, mode='rb', closefd=False)
+    return reader.readline()
+
+
 # Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
 # because pty code is not too portable.
@@ -97,14 +114,14 @@ def test_basic(self):
         debug("Writing to slave_fd")
         os.write(slave_fd, TEST_STRING_1)
-        s1 = os.read(master_fd, 1024)
+        s1 = _readline(master_fd)
         self.assertEqual('I wish to buy a fish license.\n',
                          normalize_output(s1))
         debug("Writing chunked output")
         os.write(slave_fd, TEST_STRING_2[:5])
         os.write(slave_fd, TEST_STRING_2[5:])
-        s2 = os.read(master_fd, 1024)
+        s2 = _readline(master_fd)
         self.assertEqual('For my pet fish, Eric.\n', normalize_output(s2))
         os.close(slave_fd)
SOURCES/00298-do-not-send-IP-in-SNI-TLS-extension.patch
New file
@@ -0,0 +1,60 @@
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index d0a3830..51b192c 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -50,6 +50,11 @@
 #include <sys/poll.h>
 #endif
+#ifndef MS_WINDOWS
+/* inet_pton */
+#include <arpa/inet.h>
+#endif
+
 /* Include OpenSSL header files */
 #include "openssl/rsa.h"
 #include "openssl/crypto.h"
@@ -493,8 +498,41 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
     SSL_set_mode(self->ssl, mode);
 #if HAVE_SNI
-    if (server_hostname != NULL)
-        SSL_set_tlsext_host_name(self->ssl, server_hostname);
+    if (server_hostname != NULL) {
+/* Don't send SNI for IP addresses. We cannot simply use inet_aton() and
+ * inet_pton() here. inet_aton() may be linked weakly and inet_pton() isn't
+ * available on all platforms. Use OpenSSL's IP address parser. It's
+ * available since 1.0.2 and LibreSSL since at least 2.3.0. */
+        int send_sni = 1;
+#if OPENSSL_VERSION_NUMBER >= 0x10200000L
+        ASN1_OCTET_STRING *ip = a2i_IPADDRESS(server_hostname);
+        if (ip == NULL) {
+            send_sni = 1;
+            ERR_clear_error();
+        } else {
+            send_sni = 0;
+            ASN1_OCTET_STRING_free(ip);
+        }
+#elif defined(HAVE_INET_PTON)
+#ifdef ENABLE_IPV6
+        char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
+#else
+        char packed[sizeof(struct in_addr)];
+#endif /* ENABLE_IPV6 */
+        if (inet_pton(AF_INET, server_hostname, packed)) {
+            send_sni = 0;
+#ifdef ENABLE_IPV6
+        } else if(inet_pton(AF_INET6, server_hostname, packed)) {
+            send_sni = 0;
+#endif /* ENABLE_IPV6 */
+        } else {
+            send_sni = 1;
+        }
+#endif /* HAVE_INET_PTON */
+        if (send_sni) {
+            SSL_set_tlsext_host_name(self->ssl, server_hostname);
+        }
+    }
 #endif
     /* If the socket is in non-blocking mode or timeout mode, set the BIO
SOURCES/00299-fix-ssl-module-pymax.patch
New file
@@ -0,0 +1,24 @@
From 439956a149f8a3eb44646498c63b2ef3337d5f3d Mon Sep 17 00:00:00 2001
From: Christian Heimes <christian@python.org>
Date: Sun, 25 Feb 2018 13:08:05 +0100
Subject: [PATCH] Fix ssl module, Python 2.7 doesn't have Py_MAX (#5878)
Signed-off-by: Christian Heimes <christian@python.org>
---
 Modules/_ssl.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index af66a581e15a..f9ed94dee1e1 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -610,7 +610,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
         }
 #elif defined(HAVE_INET_PTON)
 #ifdef ENABLE_IPV6
-        char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
+    #define PySSL_MAX(x, y) (((x) > (y)) ? (x) : (y))
+        char packed[PySSL_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
 #else
         char packed[sizeof(struct in_addr)];
 #endif /* ENABLE_IPV6 */
SOURCES/00303-CVE-2018-1060-1.patch
New file
@@ -0,0 +1,86 @@
diff --git a/Lib/difflib.py b/Lib/difflib.py
index 1c6fbdbedcb7..788a92df3f89 100644
--- a/Lib/difflib.py
+++ b/Lib/difflib.py
@@ -1103,7 +1103,7 @@ def _qformat(self, aline, bline, atags, btags):
 import re
-def IS_LINE_JUNK(line, pat=re.compile(r"\s*#?\s*$").match):
+def IS_LINE_JUNK(line, pat=re.compile(r"\s*(?:#\s*)?$").match):
     r"""
     Return 1 for ignorable line: iff `line` is blank or contains a single '#'.
diff --git a/Lib/poplib.py b/Lib/poplib.py
index b91e5f72d2ca..a238510b38fc 100644
--- a/Lib/poplib.py
+++ b/Lib/poplib.py
@@ -274,7 +274,7 @@ def rpop(self, user):
         return self._shortcmd('RPOP %s' % user)
-    timestamp = re.compile(r'\+OK.*(<[^>]+>)')
+    timestamp = re.compile(br'\+OK.[^<]*(<.*>)')
     def apop(self, user, secret):
         """Authorisation
diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py
index 35f2c36ca70a..d8277b79b880 100644
--- a/Lib/test/test_difflib.py
+++ b/Lib/test/test_difflib.py
@@ -269,13 +269,33 @@ def test_range_format_context(self):
         self.assertEqual(fmt(3,6), '4,6')
         self.assertEqual(fmt(0,0), '0')
+class TestJunkAPIs(unittest.TestCase):
+    def test_is_line_junk_true(self):
+        for line in ['#', '  ', ' #', '# ', ' # ', '']:
+            self.assertTrue(difflib.IS_LINE_JUNK(line), repr(line))
+
+    def test_is_line_junk_false(self):
+        for line in ['##', ' ##', '## ', 'abc ', 'abc #', 'Mr. Moose is up!']:
+            self.assertFalse(difflib.IS_LINE_JUNK(line), repr(line))
+
+    def test_is_line_junk_REDOS(self):
+        evil_input = ('\t' * 1000000) + '##'
+        self.assertFalse(difflib.IS_LINE_JUNK(evil_input))
+
+    def test_is_character_junk_true(self):
+        for char in [' ', '\t']:
+            self.assertTrue(difflib.IS_CHARACTER_JUNK(char), repr(char))
+
+    def test_is_character_junk_false(self):
+        for char in ['a', '#', '\n', '\f', '\r', '\v']:
+            self.assertFalse(difflib.IS_CHARACTER_JUNK(char), repr(char))
 def test_main():
     difflib.HtmlDiff._default_prefix = 0
     Doctests = doctest.DocTestSuite(difflib)
     run_unittest(
         TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs,
-        TestOutputFormat, Doctests)
+        TestOutputFormat, TestJunkAPIs)
 if __name__ == '__main__':
     test_main()
diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py
index 23d688724b95..d2143759ba66 100644
--- a/Lib/test/test_poplib.py
+++ b/Lib/test/test_poplib.py
@@ -211,6 +211,16 @@ def test_noop(self):
     def test_rpop(self):
         self.assertOK(self.client.rpop('foo'))
+    def test_apop_REDOS(self):
+        # Replace welcome with very long evil welcome.
+        # NB The upper bound on welcome length is currently 2048.
+        # At this length, evil input makes each apop call take
+        # on the order of milliseconds instead of microseconds.
+        evil_welcome = b'+OK' + (b'<' * 1000000)
+        with test_support.swap_attr(self.client, 'welcome', evil_welcome):
+            # The evil welcome is invalid, so apop should throw.
+            self.assertRaises(poplib.error_proto, self.client.apop, 'a', 'kb')
+
     def test_top(self):
         expected =  ('+OK 116 bytes',
                      ['From: postmaster@python.org', 'Content-Type: text/plain',
SOURCES/00306-fix-oserror-17-upon-semaphores-creation.patch
New file
@@ -0,0 +1,44 @@
# HG changeset patch
# User Charles-Fran├žois Natali <cf.natali@gmail.com>
# Date 1455316761 0
# Node ID d3662c088db8fb2c89f754031f18b1543419fed9
# Parent  5715a6d9ff12053e81f7ad75268ac059b079b351
Issue #24303: Fix random EEXIST upon multiprocessing semaphores creation with
Linux PID namespaces enabled.
diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c
--- a/Modules/_multiprocessing/semaphore.c
+++ b/Modules/_multiprocessing/semaphore.c
@@ -429,7 +429,7 @@ semlock_new(PyTypeObject *type, PyObject
     int kind, maxvalue, value;
     PyObject *result;
     static char *kwlist[] = {"kind", "value", "maxvalue", NULL};
-    static int counter = 0;
+    int try = 0;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwlist,
                                      &kind, &value, &maxvalue))
@@ -440,10 +440,18 @@ semlock_new(PyTypeObject *type, PyObject
         return NULL;
     }
-    PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%d", (long)getpid(), counter++);
+    /* Create a semaphore with a unique name. The bytes returned by
+     * _PyOS_URandom() are treated as unsigned long to ensure that the filename
+     * is valid (no special characters). */
+    do {
+        unsigned long suffix;
+        _PyOS_URandom((char *)&suffix, sizeof(suffix));
+        PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%lu", (long)getpid(),
+                      suffix);
+        SEM_CLEAR_ERROR();
+        handle = SEM_CREATE(buffer, value, maxvalue);
+    } while ((handle == SEM_FAILED) && (errno == EEXIST) && (++try < 100));
-    SEM_CLEAR_ERROR();
-    handle = SEM_CREATE(buffer, value, maxvalue);
     /* On Windows we should fail if GetLastError()==ERROR_ALREADY_EXISTS */
     if (handle == SEM_FAILED || SEM_GET_LAST_ERROR() != 0)
         goto failure;
SPECS/python.spec
@@ -1,3 +1,4 @@
# ======================================================
# Conditionals and other variables controlling the build
# ======================================================
@@ -49,6 +50,13 @@
%global with_valgrind 1
%else
%global with_valgrind 0
%endif
# Having more than 28 cores on a PPC machine will lead to race conditions
# during build so we have to set a limit.
# See: https://bugzilla.redhat.com/show_bug.cgi?id=1568974
%ifarch ppc %{power64} &&  %_smp_ncpus_max > 28
%global _smp_ncpus_max 28
%endif
%global with_gdbm 1
@@ -106,7 +114,7 @@
Name: %{python}
# Remember to also rebase python-docs when changing this:
Version: 2.7.5
Release: 69%{?dist}
Release: 76%{?dist}
License: Python
Group: Development/Languages
Requires: %{python}-libs%{?_isa} = %{version}-%{release}
@@ -1204,6 +1212,12 @@
# Resolves: rhbz#1468410
Patch282: 00282-obmalloc-mmap-threshold.patch
# 00285 #
# Fix nondeterministic read in test_pty which fails randomly in brew.
# FIXED UPSTREAM: https://bugs.python.org/issue31158
# Resolves: rhbz#1512160
Patch285: 00285-fix-non-deterministic-read-in-test_pty.patch
# 00287 #
# On the creation of io.FileIO() and builtin file() objects the GIL is now released
# when checking the file descriptor. io.FileIO.readall(), io.FileIO.read(), and
@@ -1228,11 +1242,39 @@
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1546351
Patch296: 00296-Readd-the-private-_set_hostport-api-to-httplib.patch
# 00298 #
# The SSL module no longer sends IP addresses in SNI TLS extension on
# platforms with OpenSSL 1.0.2+ or inet_pton.
# FIXED UPSTREAM: https://bugs.python.org/issue32185
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1555314
Patch298: 00298-do-not-send-IP-in-SNI-TLS-extension.patch
# 00299 #
# Fix ssl module, Python 2.7 doesn't have Py_MAX
# The previous patch 298 broke python2. This is a fixup.
# FIXED UPSTREAM: https://github.com/python/cpython/pull/5878
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1555314
Patch299: 00299-fix-ssl-module-pymax.patch
# 00303 #
# Fix CVE-2018-1060 and CVE-2018-1061
# FIXED UPSTREAM: https://bugs.python.org/issue32981
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1563454
# and https://bugzilla.redhat.com/show_bug.cgi?id=1549192
Patch303: 00303-CVE-2018-1060-1.patch
# 00305 #
# Remove 3DES from the cipher list to mitigate CVE-2016-2183 (sweet32).
# FIXED UPSTREAM: https://bugs.python.org/issue27850
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1584545
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1581901
Patch305: 00305-CVE-2016-2183.patch
# 00306 #
# Fix OSERROR 17 due to _multiprocessing/semaphore.c
# assuming a one-to-one Pid -> process mapping
# FIXED UPSTREAM: https://bugs.python.org/issue24303
# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1579432
Patch306: 00306-fix-oserror-17-upon-semaphores-creation.patch
# (New patches go here ^^^)
#
@@ -1266,7 +1308,6 @@
%if %{main_python}
Obsoletes: Distutils
Provides: Distutils
Obsoletes: python2
Provides: python2 = %{version}
Obsoletes: python-elementtree <= 1.2.6
Obsoletes: python-sqlite < 2.3.2
@@ -1330,6 +1371,9 @@
# prevent "import pyexpat" from failing with a linker error if someone hasn't
# yet upgraded expat:
Requires: expat >= 2.1.0
Provides: python2-libs = %{version}-%{release}
Provides: python2-libs%{?_isa} = %{version}-%{release}
%description libs
This package contains runtime libraries for use by Python:
@@ -1655,10 +1699,15 @@
%patch276 -p1
%patch281 -p1
%patch282 -p1
%patch285 -p1
%patch287 -p1
%patch295 -p1
%patch296 -p1
%patch298 -p1
%patch299 -p1
%patch303 -p1
%patch305 -p1
%patch306 -p1
# This shouldn't be necesarry, but is right now (2.2a3)
@@ -2107,6 +2156,10 @@
mkdir %{buildroot}%{_tmpfilesdir}
cp %{SOURCE9} %{buildroot}%{_tmpfilesdir}/python.conf
# Create the platform-python symlink pointing to usr/bin/python2.7
mkdir -p %{buildroot}%{_libexecdir}
ln -s %{_bindir}/python%{pybasever} %{buildroot}%{_libexecdir}/platform-python
# ======================================================
# Running the upstream test suite
# ======================================================
@@ -2194,6 +2247,9 @@
%{_bindir}/python2
%endif
%{_bindir}/python%{pybasever}
%{_libexecdir}/platform-python
%{_mandir}/*/*
%files libs
@@ -2532,9 +2588,40 @@
# ======================================================
%changelog
* Wed May 30 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-70
* Mon Sep 10 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-76
- Remove an unversioned obsoletes tag
Resolves: rhbz#1627059
* Mon Jul 16 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-75
- Provide the /usr/libexec/platform-python symlink to the main binary
Resolves: rhbz#1599159
* Tue Jun 12 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-74
- Fix OSERROR 17 due to _multiprocessing/semaphore.c assuming
  a one-to-one Pid -> process mapping
Resolves: rhbz#1579432
* Wed May 30 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-73
- Remove 3DS cipher to mitigate CVE-2016-2183 (sweet32).
Resolves: rhbz#1584545
Resolves: rhbz#1581901
* Thu May 03 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-72
- Fix CVE-2018-1060 and CVE-2018-1061
Resolves: rhbz#1563454 and rhbz#1549192
- Provide python2-libs from the python-libs subpackage
Resolves: rhbz#1557460
* Wed Apr 18 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-71
- Limit the number of CPU cores when building the package on power architectures
Resolves: rhbz#1568974
* Tue Apr 17 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-70
- Do not send IP addresses in SNI TLS extension
Resolves: rhbz#1555314
* Tue Apr 17 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-69
- Fix nondeterministic read in test_pty
Resolves: rhbz#1512160
* Mon Feb 19 2018 Tomas Orsava <torsava@redhat.com> - 2.7.5-68
- Add Conflicts tag with old virtualenv versions due to new behaviour of