fix some CVE and update spec
This commit is contained in:
parent
11db1f8d64
commit
f3e7b3de9b
101
CVE-2018-20852.patch
Normal file
101
CVE-2018-20852.patch
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
diff -uNrp a/Lib/cookielib.py b/Lib/cookielib.py
|
||||||
|
--- a/Lib/cookielib.py 2019-12-21 16:06:12.476000000 +0800
|
||||||
|
+++ b/Lib/cookielib.py 2019-12-21 16:09:31.556000000 +0800
|
||||||
|
@@ -1139,6 +1139,12 @@ class DefaultCookiePolicy(CookiePolicy):
|
||||||
|
req_host, erhn = eff_request_host(request)
|
||||||
|
domain = cookie.domain
|
||||||
|
|
||||||
|
+ if domain and not domain.startswith("."):
|
||||||
|
+ dotdomain = "." + domain
|
||||||
|
+ else:
|
||||||
|
+ dotdomain = domain
|
||||||
|
+
|
||||||
|
+
|
||||||
|
# strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't
|
||||||
|
if (cookie.version == 0 and
|
||||||
|
(self.strict_ns_domain & self.DomainStrictNonDomain) and
|
||||||
|
@@ -1151,7 +1157,7 @@ class DefaultCookiePolicy(CookiePolicy):
|
||||||
|
_debug(" effective request-host name %s does not domain-match "
|
||||||
|
"RFC 2965 cookie domain %s", erhn, domain)
|
||||||
|
return False
|
||||||
|
- if cookie.version == 0 and not ("."+erhn).endswith(domain):
|
||||||
|
+ if cookie.version == 0 and not ("."+erhn).endswith(dotdomain):
|
||||||
|
_debug(" request-host %s does not match Netscape cookie domain "
|
||||||
|
"%s", req_host, domain)
|
||||||
|
return False
|
||||||
|
@@ -1165,7 +1171,11 @@ class DefaultCookiePolicy(CookiePolicy):
|
||||||
|
req_host = "."+req_host
|
||||||
|
if not erhn.startswith("."):
|
||||||
|
erhn = "."+erhn
|
||||||
|
- if not (req_host.endswith(domain) or erhn.endswith(domain)):
|
||||||
|
+ if domain and not domain.startswith("."):
|
||||||
|
+ dotdomain = "." + domain
|
||||||
|
+ else:
|
||||||
|
+ dotdomain = domain
|
||||||
|
+ if not (req_host.endswith(dotdomain) or erhn.endswith(dotdomain)):
|
||||||
|
#_debug(" request domain %s does not match cookie domain %s",
|
||||||
|
# req_host, domain)
|
||||||
|
return False
|
||||||
|
diff -uNrp a/Lib/test/test_cookielib.py b/Lib/test/test_cookielib.py
|
||||||
|
--- a/Lib/test/test_cookielib.py 2019-12-21 16:06:12.640000000 +0800
|
||||||
|
+++ b/Lib/test/test_cookielib.py 2019-12-21 16:11:53.888000000 +0800
|
||||||
|
@@ -368,6 +368,7 @@ class CookieTests(TestCase):
|
||||||
|
("http://foo.bar.com/", ".foo.bar.com", True),
|
||||||
|
("http://foo.bar.com/", "foo.bar.com", True),
|
||||||
|
("http://foo.bar.com/", ".bar.com", True),
|
||||||
|
+ ("http://foo.bar.com/", "bar.com", True),
|
||||||
|
("http://foo.bar.com/", "com", True),
|
||||||
|
("http://foo.com/", "rhubarb.foo.com", False),
|
||||||
|
("http://foo.com/", ".foo.com", True),
|
||||||
|
@@ -378,6 +379,8 @@ class CookieTests(TestCase):
|
||||||
|
("http://foo/", "foo", True),
|
||||||
|
("http://foo/", "foo.local", True),
|
||||||
|
("http://foo/", ".local", True),
|
||||||
|
+ ("http://barfoo.com", ".foo.com", False),
|
||||||
|
+ ("http://barfoo.com", "foo.com", False),
|
||||||
|
]:
|
||||||
|
request = urllib2.Request(url)
|
||||||
|
r = pol.domain_return_ok(domain, request)
|
||||||
|
@@ -938,6 +941,34 @@ class CookieTests(TestCase):
|
||||||
|
c.add_cookie_header(req)
|
||||||
|
self.assertFalse(req.has_header("Cookie"))
|
||||||
|
|
||||||
|
+ c.clear()
|
||||||
|
+
|
||||||
|
+ pol.set_blocked_domains([])
|
||||||
|
+ req = Request("http://acme.com/")
|
||||||
|
+ res = FakeResponse(headers, "http://acme.com/")
|
||||||
|
+ cookies = c.make_cookies(res, req)
|
||||||
|
+ c.extract_cookies(res, req)
|
||||||
|
+ self.assertEqual(len(c), 1)
|
||||||
|
+
|
||||||
|
+ req = Request("http://acme.com/")
|
||||||
|
+ c.add_cookie_header(req)
|
||||||
|
+ self.assertTrue(req.has_header("Cookie"))
|
||||||
|
+
|
||||||
|
+ req = Request("http://badacme.com/")
|
||||||
|
+ c.add_cookie_header(req)
|
||||||
|
+ self.assertFalse(pol.return_ok(cookies[0], req))
|
||||||
|
+ self.assertFalse(req.has_header("Cookie"))
|
||||||
|
+
|
||||||
|
+ p = pol.set_blocked_domains(["acme.com"])
|
||||||
|
+ req = Request("http://acme.com/")
|
||||||
|
+ c.add_cookie_header(req)
|
||||||
|
+ self.assertFalse(req.has_header("Cookie"))
|
||||||
|
+
|
||||||
|
+ req = Request("http://badacme.com/")
|
||||||
|
+ c.add_cookie_header(req)
|
||||||
|
+ self.assertFalse(req.has_header("Cookie"))
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_secure(self):
|
||||||
|
from cookielib import CookieJar, DefaultCookiePolicy
|
||||||
|
|
||||||
|
diff -uNrp a/Misc/NEWS.d/next/Security/2019-05-20-00-35-12.bpo-35121.RRi-HU.rst b/Misc/NEWS.d/next/Security/2019-05-20-00-35-12.bpo-35121.RRi-HU.rst
|
||||||
|
--- a/Misc/NEWS.d/next/Security/2019-05-20-00-35-12.bpo-35121.RRi-HU.rst 1970-01-01 08:00:00.000000000 +0800
|
||||||
|
+++ b/Misc/NEWS.d/next/Security/2019-05-20-00-35-12.bpo-35121.RRi-HU.rst 2019-12-21 16:12:17.416000000 +0800
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+Don't send cookies of domain A without Domain attribute to domain B when
|
||||||
|
+domain A is a suffix match of domain B while using a cookiejar with
|
||||||
|
+:class:`cookielib.DefaultCookiePolicy` policy. Patch by Karthikeyan
|
||||||
|
+Singaravelan.
|
||||||
45
CVE-2019-10160-1.patch
Normal file
45
CVE-2019-10160-1.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
diff -uNrp a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
|
||||||
|
--- a/Lib/test/test_urlparse.py 2019-12-21 15:41:32.172000000 +0800
|
||||||
|
+++ b/Lib/test/test_urlparse.py 2019-12-21 15:44:28.316000000 +0800
|
||||||
|
@@ -641,6 +641,12 @@ class UrlParseTestCase(unittest.TestCase
|
||||||
|
self.assertIn(u'\u2100', denorm_chars)
|
||||||
|
self.assertIn(u'\uFF03', denorm_chars)
|
||||||
|
|
||||||
|
+ # bpo-36742: Verify port separators are ignored when they
|
||||||
|
+ # existed prior to decomposition
|
||||||
|
+ urlparse.urlsplit(u'http://\u30d5\u309a:80')
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ urlparse.urlsplit(u'http://\u30d5\u309a\ufe1380')
|
||||||
|
+
|
||||||
|
for scheme in [u"http", u"https", u"ftp"]:
|
||||||
|
for c in denorm_chars:
|
||||||
|
url = u"{}://netloc{}false.netloc/path".format(scheme, c)
|
||||||
|
diff -uNrp a/Lib/urlparse.py b/Lib/urlparse.py
|
||||||
|
--- a/Lib/urlparse.py 2019-12-21 15:41:32.080000000 +0800
|
||||||
|
+++ b/Lib/urlparse.py 2019-12-21 15:46:11.480000000 +0800
|
||||||
|
@@ -171,13 +171,17 @@ def _checknetloc(netloc):
|
||||||
|
# looking for characters like \u2100 that expand to 'a/c'
|
||||||
|
# IDNA uses NFKC equivalence, so normalize for this check
|
||||||
|
import unicodedata
|
||||||
|
- netloc2 = unicodedata.normalize('NFKC', netloc)
|
||||||
|
- if netloc == netloc2:
|
||||||
|
+ n = netloc.rpartition('@')[2] # ignore anything to the left of '@'
|
||||||
|
+ n = n.replace(':', '') # ignore characters already included
|
||||||
|
+ n = n.replace('#', '') # but not the surrounding text
|
||||||
|
+ n = n.replace('?', '')
|
||||||
|
+ netloc2 = unicodedata.normalize('NFKC', n)
|
||||||
|
+ if n == netloc2:
|
||||||
|
return
|
||||||
|
_, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay
|
||||||
|
for c in '/?#@:':
|
||||||
|
if c in netloc2:
|
||||||
|
- raise ValueError("netloc '" + netloc2 + "' contains invalid " +
|
||||||
|
+ raise ValueError("netloc '" + netloc + "' contains invalid " +
|
||||||
|
"characters under NFKC normalization")
|
||||||
|
|
||||||
|
def urlsplit(url, scheme='', allow_fragments=True):
|
||||||
|
diff -uNrp a/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst b/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst
|
||||||
|
--- a/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst 1970-01-01 08:00:00.000000000 +0800
|
||||||
|
+++ b/Misc/NEWS.d/next/Security/2019-04-29-15-34-59.bpo-36742.QCUY0i.rst 2019-12-21 15:53:31.188000000 +0800
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Fixes mishandling of pre-normalization characters in urlsplit().
|
||||||
50
CVE-2019-10160-2.patch
Normal file
50
CVE-2019-10160-2.patch
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
diff -uNrp a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
|
||||||
|
--- a/Lib/test/test_urlparse.py 2019-12-21 15:54:46.576000000 +0800
|
||||||
|
+++ b/Lib/test/test_urlparse.py 2019-12-21 15:56:22.440000000 +0800
|
||||||
|
@@ -648,11 +648,13 @@ class UrlParseTestCase(unittest.TestCase
|
||||||
|
urlparse.urlsplit(u'http://\u30d5\u309a\ufe1380')
|
||||||
|
|
||||||
|
for scheme in [u"http", u"https", u"ftp"]:
|
||||||
|
- for c in denorm_chars:
|
||||||
|
- url = u"{}://netloc{}false.netloc/path".format(scheme, c)
|
||||||
|
- print "Checking %r" % url
|
||||||
|
- with self.assertRaises(ValueError):
|
||||||
|
- urlparse.urlsplit(url)
|
||||||
|
+ for netloc in [u"netloc{}false.netloc", u"n{}user@netloc"]:
|
||||||
|
+ for c in denorm_chars:
|
||||||
|
+ url = u"{}://{}/path".format(scheme, netloc.format(c))
|
||||||
|
+ if test_support.verbose:
|
||||||
|
+ print "Checking %r" % url
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ urlparse.urlsplit(url)
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
test_support.run_unittest(UrlParseTestCase)
|
||||||
|
diff -uNrp a/Lib/urlparse.py b/Lib/urlparse.py
|
||||||
|
--- a/Lib/urlparse.py 2019-12-21 15:54:46.344000000 +0800
|
||||||
|
+++ b/Lib/urlparse.py 2019-12-21 15:57:41.260000000 +0800
|
||||||
|
@@ -171,18 +171,18 @@ def _checknetloc(netloc):
|
||||||
|
# looking for characters like \u2100 that expand to 'a/c'
|
||||||
|
# IDNA uses NFKC equivalence, so normalize for this check
|
||||||
|
import unicodedata
|
||||||
|
- n = netloc.rpartition('@')[2] # ignore anything to the left of '@'
|
||||||
|
- n = n.replace(':', '') # ignore characters already included
|
||||||
|
- n = n.replace('#', '') # but not the surrounding text
|
||||||
|
- n = n.replace('?', '')
|
||||||
|
+ n = netloc.replace(u'@', u'') # ignore characters already included
|
||||||
|
+ n = n.replace(u':', u'') # but not the surrounding text
|
||||||
|
+ n = n.replace(u'#', u'')
|
||||||
|
+ n = n.replace(u'?', u'')
|
||||||
|
netloc2 = unicodedata.normalize('NFKC', n)
|
||||||
|
if n == netloc2:
|
||||||
|
return
|
||||||
|
_, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay
|
||||||
|
for c in '/?#@:':
|
||||||
|
if c in netloc2:
|
||||||
|
- raise ValueError("netloc '" + netloc + "' contains invalid " +
|
||||||
|
- "characters under NFKC normalization")
|
||||||
|
+ raise ValueError(u"netloc '" + netloc + u"' contains invalid " +
|
||||||
|
+ u"characters under NFKC normalization")
|
||||||
|
|
||||||
|
def urlsplit(url, scheme='', allow_fragments=True):
|
||||||
|
"""Parse a URL into 5 components:
|
||||||
41
CVE-2019-10160-3.patch
Normal file
41
CVE-2019-10160-3.patch
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
diff -uNrp a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
|
||||||
|
--- a/Lib/test/test_urlparse.py 2019-12-21 15:58:00.556000000 +0800
|
||||||
|
+++ b/Lib/test/test_urlparse.py 2019-12-21 15:59:11.456000000 +0800
|
||||||
|
@@ -656,6 +656,15 @@ class UrlParseTestCase(unittest.TestCase
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
urlparse.urlsplit(url)
|
||||||
|
|
||||||
|
+ # check error message: invalid netloc must be formated with repr()
|
||||||
|
+ # to get an ASCII error message
|
||||||
|
+ with self.assertRaises(ValueError) as cm:
|
||||||
|
+ urlparse.urlsplit(u'http://example.com\uFF03@bing.com')
|
||||||
|
+ self.assertEqual(str(cm.exception),
|
||||||
|
+ "netloc u'example.com\\uff03@bing.com' contains invalid characters "
|
||||||
|
+ "under NFKC normalization")
|
||||||
|
+ self.assertIsInstance(cm.exception.args[0], str)
|
||||||
|
+
|
||||||
|
def test_main():
|
||||||
|
test_support.run_unittest(UrlParseTestCase)
|
||||||
|
|
||||||
|
diff -uNrp a/Lib/urlparse.py b/Lib/urlparse.py
|
||||||
|
--- a/Lib/urlparse.py 2019-12-21 15:58:00.480000000 +0800
|
||||||
|
+++ b/Lib/urlparse.py 2019-12-21 15:59:55.128000000 +0800
|
||||||
|
@@ -181,8 +181,9 @@ def _checknetloc(netloc):
|
||||||
|
_, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay
|
||||||
|
for c in '/?#@:':
|
||||||
|
if c in netloc2:
|
||||||
|
- raise ValueError(u"netloc '" + netloc + u"' contains invalid " +
|
||||||
|
- u"characters under NFKC normalization")
|
||||||
|
+ raise ValueError("netloc %r contains invalid characters "
|
||||||
|
+ "under NFKC normalization"
|
||||||
|
+ % netloc)
|
||||||
|
|
||||||
|
def urlsplit(url, scheme='', allow_fragments=True):
|
||||||
|
"""Parse a URL into 5 components:
|
||||||
|
diff -uNrp a/Misc/NEWS.d/next/Library/2019-06-10-12-02-45.bpo-36742.UEdHXJ.rst b/Misc/NEWS.d/next/Library/2019-06-10-12-02-45.bpo-36742.UEdHXJ.rst
|
||||||
|
--- a/Misc/NEWS.d/next/Library/2019-06-10-12-02-45.bpo-36742.UEdHXJ.rst 1970-01-01 08:00:00.000000000 +0800
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2019-06-10-12-02-45.bpo-36742.UEdHXJ.rst 2019-12-21 16:00:40.480000000 +0800
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+:func:`urlparse.urlsplit` error message for invalid ``netloc`` according to
|
||||||
|
+NFKC normalization is now a :class:`str` string, rather than a
|
||||||
|
+:class:`unicode` string, to prevent error when displaying the error.
|
||||||
57
CVE-2019-16056.patch
Normal file
57
CVE-2019-16056.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
diff -uNrp a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py
|
||||||
|
--- a/Lib/email/_parseaddr.py 2019-12-21 16:01:21.340000000 +0800
|
||||||
|
+++ b/Lib/email/_parseaddr.py 2019-12-21 16:03:22.108000000 +0800
|
||||||
|
@@ -336,7 +336,12 @@ class AddrlistClass:
|
||||||
|
aslist.append('@')
|
||||||
|
self.pos += 1
|
||||||
|
self.gotonext()
|
||||||
|
- return EMPTYSTRING.join(aslist) + self.getdomain()
|
||||||
|
+ domain = self.getdomain()
|
||||||
|
+ if not domain:
|
||||||
|
+ # Invalid domain, return an empty address instead of returning a
|
||||||
|
+ # local part to denote failed parsing.
|
||||||
|
+ return EMPTYSTRING
|
||||||
|
+ return EMPTYSTRING.join(aslist) + domain
|
||||||
|
|
||||||
|
def getdomain(self):
|
||||||
|
"""Get the complete domain name from an address."""
|
||||||
|
@@ -351,6 +356,10 @@ class AddrlistClass:
|
||||||
|
elif self.field[self.pos] == '.':
|
||||||
|
self.pos += 1
|
||||||
|
sdlist.append('.')
|
||||||
|
+ elif self.field[self.pos] == '@':
|
||||||
|
+ # bpo-34155: Don't parse domains with two `@` like
|
||||||
|
+ # `a@malicious.org@important.com`.
|
||||||
|
+ return EMPTYSTRING
|
||||||
|
elif self.field[self.pos] in self.atomends:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
diff -uNrp a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py
|
||||||
|
--- a/Lib/email/test/test_email.py 2019-12-21 16:01:21.344000000 +0800
|
||||||
|
+++ b/Lib/email/test/test_email.py 2019-12-21 16:04:40.564000000 +0800
|
||||||
|
@@ -2306,6 +2306,20 @@ class TestMiscellaneous(TestEmailBase):
|
||||||
|
self.assertEqual(Utils.parseaddr('<>'), ('', ''))
|
||||||
|
self.assertEqual(Utils.formataddr(Utils.parseaddr('<>')), '')
|
||||||
|
|
||||||
|
+ def test_parseaddr_multiple_domains(self):
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ Utils.parseaddr('a@b@c'),
|
||||||
|
+ ('', '')
|
||||||
|
+ )
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ Utils.parseaddr('a@b.c@c'),
|
||||||
|
+ ('', '')
|
||||||
|
+ )
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ Utils.parseaddr('a@172.17.0.1@c'),
|
||||||
|
+ ('', '')
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
def test_noquote_dump(self):
|
||||||
|
self.assertEqual(
|
||||||
|
Utils.formataddr(('A Silly Person', 'person@dom.ain')),
|
||||||
|
diff -uNrp a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
|
||||||
|
--- a/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst 1970-01-01 08:00:00.000000000 +0800
|
||||||
|
+++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst 2019-12-21 16:05:05.292000000 +0800
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Fix parsing of invalid email addresses with more than one ``@`` (e.g. a@b@c.com.) to not return the part before 2nd ``@`` as valid email address. Patch by maxking & jpic.
|
||||||
74
CVE-2019-16935.patch
Normal file
74
CVE-2019-16935.patch
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
diff -uNrp a/Lib/DocXMLRPCServer.py b/Lib/DocXMLRPCServer.py
|
||||||
|
--- a/Lib/DocXMLRPCServer.py 2019-12-21 16:13:25.240000000 +0800
|
||||||
|
+++ b/Lib/DocXMLRPCServer.py 2019-12-21 16:15:24.076000000 +0800
|
||||||
|
@@ -20,6 +20,15 @@ from SimpleXMLRPCServer import (SimpleXM
|
||||||
|
CGIXMLRPCRequestHandler,
|
||||||
|
resolve_dotted_attribute)
|
||||||
|
|
||||||
|
+def _html_escape_quote(s):
|
||||||
|
+ s = s.replace("&", "&") # Must be done first!
|
||||||
|
+ s = s.replace("<", "<")
|
||||||
|
+ s = s.replace(">", ">")
|
||||||
|
+ s = s.replace('"', """)
|
||||||
|
+ s = s.replace('\'', "'")
|
||||||
|
+ return s
|
||||||
|
+
|
||||||
|
+
|
||||||
|
class ServerHTMLDoc(pydoc.HTMLDoc):
|
||||||
|
"""Class used to generate pydoc HTML document for a server"""
|
||||||
|
|
||||||
|
@@ -210,7 +219,9 @@ class XMLRPCDocGenerator:
|
||||||
|
methods
|
||||||
|
)
|
||||||
|
|
||||||
|
- return documenter.page(self.server_title, documentation)
|
||||||
|
+ title = _html_escape_quote(self.server_title)
|
||||||
|
+ return documenter.page(title, documentation)
|
||||||
|
+
|
||||||
|
|
||||||
|
class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
||||||
|
"""XML-RPC and documentation request handler class.
|
||||||
|
diff -uNrp a/Lib/test/test_docxmlrpc.py b/Lib/test/test_docxmlrpc.py
|
||||||
|
--- a/Lib/test/test_docxmlrpc.py 2019-12-21 16:13:25.340000000 +0800
|
||||||
|
+++ b/Lib/test/test_docxmlrpc.py 2019-12-21 16:16:49.828000000 +0800
|
||||||
|
@@ -1,5 +1,6 @@
|
||||||
|
from DocXMLRPCServer import DocXMLRPCServer
|
||||||
|
import httplib
|
||||||
|
+import re
|
||||||
|
import sys
|
||||||
|
from test import test_support
|
||||||
|
threading = test_support.import_module('threading')
|
||||||
|
@@ -176,6 +177,26 @@ class DocXMLRPCHTTPGETServer(unittest.Te
|
||||||
|
self.assertIn("""Try self.<strong>add</strong>, too.""",
|
||||||
|
response.read())
|
||||||
|
|
||||||
|
+ def test_server_title_escape(self):
|
||||||
|
+ """Test that the server title and documentation
|
||||||
|
+ are escaped for HTML.
|
||||||
|
+ """
|
||||||
|
+ self.serv.set_server_title('test_title<script>')
|
||||||
|
+ self.serv.set_server_documentation('test_documentation<script>')
|
||||||
|
+ self.assertEqual('test_title<script>', self.serv.server_title)
|
||||||
|
+ self.assertEqual('test_documentation<script>',
|
||||||
|
+ self.serv.server_documentation)
|
||||||
|
+
|
||||||
|
+ generated = self.serv.generate_html_documentation()
|
||||||
|
+ title = re.search(r'<title>(.+?)</title>', generated).group()
|
||||||
|
+ documentation = re.search(r'<p><tt>(.+?)</tt></p>', generated).group()
|
||||||
|
+ self.assertEqual('<title>Python: test_title<script></title>',
|
||||||
|
+ title)
|
||||||
|
+ self.assertEqual('<p><tt>test_documentation<script></tt></p>',
|
||||||
|
+ documentation)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_main():
|
||||||
|
test_support.run_unittest(DocXMLRPCHTTPGETServer)
|
||||||
|
|
||||||
|
diff -uNrp a/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst b/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst
|
||||||
|
--- a/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst 1970-01-01 08:00:00.000000000 +0800
|
||||||
|
+++ b/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst 2019-12-21 16:17:13.368000000 +0800
|
||||||
|
@@ -0,0 +1,3 @@
|
||||||
|
+Escape the server title of :class:`DocXMLRPCServer.DocXMLRPCServer`
|
||||||
|
+when rendering the document page as HTML.
|
||||||
|
+(Contributed by Dong-hee Na in :issue:`38243`.)
|
||||||
13
CVE-2019-17514.patch
Normal file
13
CVE-2019-17514.patch
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
diff -uNrp a/Doc/library/glob.rst b/Doc/library/glob.rst
|
||||||
|
--- a/Doc/library/glob.rst 2019-12-21 16:18:26.908000000 +0800
|
||||||
|
+++ b/Doc/library/glob.rst 2019-12-21 16:19:36.668000000 +0800
|
||||||
|
@@ -31,7 +31,8 @@ For example, ``'[?]'`` matches the chara
|
||||||
|
a string containing a path specification. *pathname* can be either absolute
|
||||||
|
(like :file:`/usr/src/Python-1.5/Makefile`) or relative (like
|
||||||
|
:file:`../../Tools/\*/\*.gif`), and can contain shell-style wildcards. Broken
|
||||||
|
- symlinks are included in the results (as in the shell).
|
||||||
|
+ symlinks are included in the results (as in the shell). Whether or not the
|
||||||
|
+ results are sorted depends on the file system.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: iglob(pathname)
|
||||||
128
CVE-2019-9636-bpo-36216-Add-check-for-characters.patch
Normal file
128
CVE-2019-9636-bpo-36216-Add-check-for-characters.patch
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
diff -uNrp a/Doc/library/urlparse.rst b/Doc/library/urlparse.rst
|
||||||
|
--- a/Doc/library/urlparse.rst 2019-12-21 15:21:09.836000000 +0800
|
||||||
|
+++ b/Doc/library/urlparse.rst 2019-12-21 15:34:37.812000000 +0800
|
||||||
|
@@ -119,12 +119,22 @@ The :mod:`urlparse` module defines the f
|
||||||
|
See section :ref:`urlparse-result-object` for more information on the result
|
||||||
|
object.
|
||||||
|
|
||||||
|
+ Characters in the :attr:`netloc` attribute that decompose under NFKC
|
||||||
|
+ normalization (as used by the IDNA encoding) into any of ``/``, ``?``,
|
||||||
|
+ ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is
|
||||||
|
+ decomposed before parsing, or is not a Unicode string, no error will be
|
||||||
|
+ raised
|
||||||
|
+
|
||||||
|
.. versionchanged:: 2.5
|
||||||
|
Added attributes to return value.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.7
|
||||||
|
Added IPv6 URL parsing capabilities.
|
||||||
|
|
||||||
|
+ .. versionchanged:: 2.7.17
|
||||||
|
+ Characters that affect netloc parsing under NFKC normalization will
|
||||||
|
+ now raise :exc:`ValueError`.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. function:: parse_qs(qs[, keep_blank_values[, strict_parsing[, max_num_fields]]])
|
||||||
|
|
||||||
|
@@ -232,11 +242,21 @@ The :mod:`urlparse` module defines the f
|
||||||
|
See section :ref:`urlparse-result-object` for more information on the result
|
||||||
|
object.
|
||||||
|
|
||||||
|
+ Characters in the :attr:`netloc` attribute that decompose under NFKC
|
||||||
|
+ normalization (as used by the IDNA encoding) into any of ``/``, ``?``,
|
||||||
|
+ ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is
|
||||||
|
+ decomposed before parsing, or is not a Unicode string, no error will be
|
||||||
|
+ raised.
|
||||||
|
+
|
||||||
|
.. versionadded:: 2.2
|
||||||
|
|
||||||
|
.. versionchanged:: 2.5
|
||||||
|
Added attributes to return value.
|
||||||
|
|
||||||
|
+ .. versionchanged:: 2.7.17
|
||||||
|
+ Characters that affect netloc parsing under NFKC normalization will
|
||||||
|
+ now raise :exc:`ValueError`.
|
||||||
|
+
|
||||||
|
|
||||||
|
.. function:: urlunsplit(parts)
|
||||||
|
|
||||||
|
diff -uNrp a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
|
||||||
|
--- a/Lib/test/test_urlparse.py 2019-12-21 15:21:09.456000000 +0800
|
||||||
|
+++ b/Lib/test/test_urlparse.py 2019-12-21 15:37:03.840000000 +0800
|
||||||
|
@@ -1,4 +1,6 @@
|
||||||
|
from test import test_support
|
||||||
|
+import sys
|
||||||
|
+import unicodedata
|
||||||
|
import unittest
|
||||||
|
import urlparse
|
||||||
|
|
||||||
|
@@ -623,6 +625,28 @@ class UrlParseTestCase(unittest.TestCase
|
||||||
|
self.assertEqual(urlparse.urlparse("https:"),('https','','','','',''))
|
||||||
|
self.assertEqual(urlparse.urlparse("http://www.python.org:80"),
|
||||||
|
('http','www.python.org:80','','','',''))
|
||||||
|
+
|
||||||
|
+ def test_urlsplit_normalization(self):
|
||||||
|
+ # Certain characters should never occur in the netloc,
|
||||||
|
+ # including under normalization.
|
||||||
|
+ # Ensure that ALL of them are detected and cause an error
|
||||||
|
+ illegal_chars = u'/:#?@'
|
||||||
|
+ hex_chars = {'{:04X}'.format(ord(c)) for c in illegal_chars}
|
||||||
|
+ denorm_chars = [
|
||||||
|
+ c for c in map(unichr, range(128, sys.maxunicode))
|
||||||
|
+ if (hex_chars & set(unicodedata.decomposition(c).split()))
|
||||||
|
+ and c not in illegal_chars
|
||||||
|
+ ]
|
||||||
|
+ # Sanity check that we found at least one such character
|
||||||
|
+ self.assertIn(u'\u2100', denorm_chars)
|
||||||
|
+ self.assertIn(u'\uFF03', denorm_chars)
|
||||||
|
+
|
||||||
|
+ for scheme in [u"http", u"https", u"ftp"]:
|
||||||
|
+ for c in denorm_chars:
|
||||||
|
+ url = u"{}://netloc{}false.netloc/path".format(scheme, c)
|
||||||
|
+ print "Checking %r" % url
|
||||||
|
+ with self.assertRaises(ValueError):
|
||||||
|
+ urlparse.urlsplit(url)
|
||||||
|
|
||||||
|
def test_main():
|
||||||
|
test_support.run_unittest(UrlParseTestCase)
|
||||||
|
diff -uNrp a/Lib/urlparse.py b/Lib/urlparse.py
|
||||||
|
--- a/Lib/urlparse.py 2019-12-21 15:21:09.304000000 +0800
|
||||||
|
+++ b/Lib/urlparse.py 2019-12-21 15:39:24.324000000 +0800
|
||||||
|
@@ -165,6 +165,21 @@ def _splitnetloc(url, start=0):
|
||||||
|
delim = min(delim, wdelim) # use earliest delim position
|
||||||
|
return url[start:delim], url[delim:] # return (domain, rest)
|
||||||
|
|
||||||
|
+def _checknetloc(netloc):
|
||||||
|
+ if not netloc or not isinstance(netloc, unicode):
|
||||||
|
+ return
|
||||||
|
+ # looking for characters like \u2100 that expand to 'a/c'
|
||||||
|
+ # IDNA uses NFKC equivalence, so normalize for this check
|
||||||
|
+ import unicodedata
|
||||||
|
+ netloc2 = unicodedata.normalize('NFKC', netloc)
|
||||||
|
+ if netloc == netloc2:
|
||||||
|
+ return
|
||||||
|
+ _, _, netloc = netloc.rpartition('@') # anything to the left of '@' is okay
|
||||||
|
+ for c in '/?#@:':
|
||||||
|
+ if c in netloc2:
|
||||||
|
+ raise ValueError("netloc '" + netloc2 + "' contains invalid " +
|
||||||
|
+ "characters under NFKC normalization")
|
||||||
|
+
|
||||||
|
def urlsplit(url, scheme='', allow_fragments=True):
|
||||||
|
"""Parse a URL into 5 components:
|
||||||
|
<scheme>://<netloc>/<path>?<query>#<fragment>
|
||||||
|
@@ -193,6 +208,7 @@ def urlsplit(url, scheme='', allow_fragm
|
||||||
|
url, fragment = url.split('#', 1)
|
||||||
|
if '?' in url:
|
||||||
|
url, query = url.split('?', 1)
|
||||||
|
+ _checknetloc(netloc)
|
||||||
|
v = SplitResult(scheme, netloc, url, query, fragment)
|
||||||
|
_parse_cache[key] = v
|
||||||
|
return v
|
||||||
|
@@ -216,6 +232,7 @@ def urlsplit(url, scheme='', allow_fragm
|
||||||
|
url, fragment = url.split('#', 1)
|
||||||
|
if '?' in url:
|
||||||
|
url, query = url.split('?', 1)
|
||||||
|
+ _checknetloc(netloc)
|
||||||
|
v = SplitResult(scheme, netloc, url, query, fragment)
|
||||||
|
_parse_cache[key] = v
|
||||||
|
return v
|
||||||
12
bugfix-linux_distribution-skip-link-file.patch
Normal file
12
bugfix-linux_distribution-skip-link-file.patch
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
diff -uNrp a/Lib/platform.py b/Lib/platform.py
|
||||||
|
--- a/Lib/platform.py 2019-12-21 15:00:32.420000000 +0800
|
||||||
|
+++ b/Lib/platform.py 2019-12-21 15:07:14.292000000 +0800
|
||||||
|
@@ -353,6 +353,8 @@ def linux_distribution(distname='', vers
|
||||||
|
return distname,version,id
|
||||||
|
etc.sort()
|
||||||
|
for file in etc:
|
||||||
|
+ if os.path.islink('/etc/'+file):
|
||||||
|
+ continue
|
||||||
|
m = _release_filename.match(file)
|
||||||
|
if m is not None:
|
||||||
|
_distname,dummy = m.groups()
|
||||||
33
bugfix-test_locale-and-test_codecs.patch
Normal file
33
bugfix-test_locale-and-test_codecs.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
diff -uNrp a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
|
||||||
|
--- a/Lib/test/test_codecs.py 2019-12-21 15:08:05.068000000 +0800
|
||||||
|
+++ b/Lib/test/test_codecs.py 2019-12-21 15:17:35.536000000 +0800
|
||||||
|
@@ -1427,7 +1427,7 @@ class CodecsModuleTest(unittest.TestCase
|
||||||
|
def test_lookup_issue1813(self):
|
||||||
|
# Issue #1813: under Turkish locales, lookup of some codecs failed
|
||||||
|
# because 'I' is lowercased as a dotless "i"
|
||||||
|
- oldlocale = locale.getlocale(locale.LC_CTYPE)
|
||||||
|
+ oldlocale = locale.setlocale(locale.LC_CTYPE)
|
||||||
|
self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldlocale)
|
||||||
|
try:
|
||||||
|
locale.setlocale(locale.LC_CTYPE, 'tr_TR')
|
||||||
|
diff -uNrp a/Lib/test/test_locale.py b/Lib/test/test_locale.py
|
||||||
|
--- a/Lib/test/test_locale.py 2019-12-21 15:08:05.060000000 +0800
|
||||||
|
+++ b/Lib/test/test_locale.py 2019-12-21 15:19:01.140000000 +0800
|
||||||
|
@@ -469,7 +469,7 @@ class TestMiscellaneous(unittest.TestCas
|
||||||
|
|
||||||
|
def test_getsetlocale_issue1813(self):
|
||||||
|
# Issue #1813: setting and getting the locale under a Turkish locale
|
||||||
|
- oldlocale = locale.getlocale()
|
||||||
|
+ oldlocale = locale.setlocale(locale.LC_CTYPE)
|
||||||
|
self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldlocale)
|
||||||
|
for loc in ('tr_TR', 'tr_TR.UTF-8', 'tr_TR.ISO8859-9'):
|
||||||
|
try:
|
||||||
|
@@ -494,7 +494,7 @@ class TestMiscellaneous(unittest.TestCas
|
||||||
|
self.assertEqual(locale.normalize(u'en_US'), 'en_US.ISO8859-1')
|
||||||
|
|
||||||
|
def test_setlocale_unicode(self):
|
||||||
|
- oldlocale = locale.getlocale()
|
||||||
|
+ oldlocale = locale.setlocale(locale.LC_CTYPE)
|
||||||
|
self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldlocale)
|
||||||
|
|
||||||
|
user_locale = locale.setlocale(locale.LC_CTYPE, '')
|
||||||
38
python2.spec
38
python2.spec
@ -15,7 +15,7 @@
|
|||||||
%undefine _debuginfo_subpackages
|
%undefine _debuginfo_subpackages
|
||||||
Name: python2
|
Name: python2
|
||||||
Version: 2.7.16
|
Version: 2.7.16
|
||||||
Release: 6
|
Release: 8
|
||||||
Summary: Python is an interpreted, interactive object-oriented programming language suitable
|
Summary: Python is an interpreted, interactive object-oriented programming language suitable
|
||||||
License: Python
|
License: Python
|
||||||
URL: https://www.python.org/
|
URL: https://www.python.org/
|
||||||
@ -88,6 +88,16 @@ Patch6044: python2-CVE-2019-9948-1.patch
|
|||||||
Patch6045: python2-CVE-2019-9948-2.patch
|
Patch6045: python2-CVE-2019-9948-2.patch
|
||||||
Patch6047: CVE-2019-9740.patch
|
Patch6047: CVE-2019-9740.patch
|
||||||
Patch9000: python2-add-generic-os-supportr.patch
|
Patch9000: python2-add-generic-os-supportr.patch
|
||||||
|
Patch6048: bugfix-linux_distribution-skip-link-file.patch
|
||||||
|
Patch6049: bugfix-test_locale-and-test_codecs.patch
|
||||||
|
Patch6050: CVE-2019-9636-bpo-36216-Add-check-for-characters.patch
|
||||||
|
Patch6051: CVE-2019-10160-1.patch
|
||||||
|
Patch6052: CVE-2019-10160-2.patch
|
||||||
|
Patch6053: CVE-2019-10160-3.patch
|
||||||
|
Patch6054: CVE-2019-16056.patch
|
||||||
|
Patch6055: CVE-2018-20852.patch
|
||||||
|
Patch6056: CVE-2019-16935.patch
|
||||||
|
Patch6057: CVE-2019-17514.patch
|
||||||
|
|
||||||
BuildRequires: libdb-devel libffi-devel valgrind-devel ncurses-devel expat-devel readline-devel
|
BuildRequires: libdb-devel libffi-devel valgrind-devel ncurses-devel expat-devel readline-devel
|
||||||
BuildRequires: openssl-devel libtirpc-devel tcl-devel tk-devel glibc-devel libnsl2-devel
|
BuildRequires: openssl-devel libtirpc-devel tcl-devel tk-devel glibc-devel libnsl2-devel
|
||||||
@ -164,6 +174,7 @@ Obsoletes: %{name}-test < %{version}-%{release}
|
|||||||
Obsoletes: %{name}-test%{?_isa} < %{version}-%{release}
|
Obsoletes: %{name}-test%{?_isa} < %{version}-%{release}
|
||||||
Provides: %{name}-test = %{version}-%{release}
|
Provides: %{name}-test = %{version}-%{release}
|
||||||
Provides: %{name}-test%{?_isa} = %{version}-%{release}
|
Provides: %{name}-test%{?_isa} = %{version}-%{release}
|
||||||
|
Requires: openEuler-rpm-config
|
||||||
|
|
||||||
%description devel
|
%description devel
|
||||||
This package contains libraries and header files used to build applications
|
This package contains libraries and header files used to build applications
|
||||||
@ -286,7 +297,7 @@ BuildPython optimized \
|
|||||||
python%{pybasever} \
|
python%{pybasever} \
|
||||||
true \
|
true \
|
||||||
%ifarch %{ix86} x86_64
|
%ifarch %{ix86} x86_64
|
||||||
"--enable-optimizations"
|
"--disable-optimizations" \
|
||||||
%else
|
%else
|
||||||
""
|
""
|
||||||
%endif
|
%endif
|
||||||
@ -375,6 +386,7 @@ for Dir in python%{pybasever} python%{pybasever}-debug ; do
|
|||||||
#endif
|
#endif
|
||||||
EOF
|
EOF
|
||||||
done
|
done
|
||||||
|
ln -s ../../libpython%{pybasever}.so %{buildroot}%{pylibdir}/config/libpython%{pybasever}.so
|
||||||
|
|
||||||
#with systemtap
|
#with systemtap
|
||||||
mkdir -p %{buildroot}%{tapsetdir}
|
mkdir -p %{buildroot}%{tapsetdir}
|
||||||
@ -455,7 +467,6 @@ sed -e "s|LIBRARY_PATH|%{_libdir}/%{py_INSTSONAME_debug}|" %{SOURCE1} \
|
|||||||
%{pylibdir}/test/script_helper.py*
|
%{pylibdir}/test/script_helper.py*
|
||||||
%{pylibdir}/test/test_support.py*
|
%{pylibdir}/test/test_support.py*
|
||||||
|
|
||||||
|
|
||||||
%files tkinter
|
%files tkinter
|
||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%{pylibdir}/lib-tk
|
%{pylibdir}/lib-tk
|
||||||
@ -469,6 +480,8 @@ sed -e "s|LIBRARY_PATH|%{_libdir}/%{py_INSTSONAME_debug}|" %{SOURCE1} \
|
|||||||
%{_libdir}/pkgconfig/python*.pc
|
%{_libdir}/pkgconfig/python*.pc
|
||||||
%{_libdir}/libpython%{pybasever}.so
|
%{_libdir}/libpython%{pybasever}.so
|
||||||
%{_bindir}/python*-config
|
%{_bindir}/python*-config
|
||||||
|
%{pylibdir}/distutils/command/wininst-*.exe
|
||||||
|
%doc Misc/README.valgrind Misc/valgrind-python.supp Misc/gdbinit
|
||||||
|
|
||||||
#Tests
|
#Tests
|
||||||
%{pylibdir}/bsddb/test
|
%{pylibdir}/bsddb/test
|
||||||
@ -479,6 +492,16 @@ sed -e "s|LIBRARY_PATH|%{_libdir}/%{py_INSTSONAME_debug}|" %{SOURCE1} \
|
|||||||
%{pylibdir}/lib2to3/tests
|
%{pylibdir}/lib2to3/tests
|
||||||
%{pylibdir}/sqlite3/test
|
%{pylibdir}/sqlite3/test
|
||||||
%{pylibdir}/test/*
|
%{pylibdir}/test/*
|
||||||
|
%exclude %{pylibdir}/test/allsans.pem
|
||||||
|
%exclude %{pylibdir}/test/badcert.pem
|
||||||
|
%exclude %{pylibdir}/test/badkey.pem
|
||||||
|
%exclude %{pylibdir}/test/keycert2.pem
|
||||||
|
%exclude %{pylibdir}/test/keycert3.pem
|
||||||
|
%exclude %{pylibdir}/test/keycert4.pem
|
||||||
|
%exclude %{pylibdir}/test/keycert.pem
|
||||||
|
%exclude %{pylibdir}/test/ssl_key.pem
|
||||||
|
%exclude %{pylibdir}/test/ssl_key.passwd.pem
|
||||||
|
%exclude %{pylibdir}/test/keycert.passwd.pem
|
||||||
%exclude %{pylibdir}/test/__init__.py*
|
%exclude %{pylibdir}/test/__init__.py*
|
||||||
%exclude %{pylibdir}/test/support/
|
%exclude %{pylibdir}/test/support/
|
||||||
%exclude %{pylibdir}/test/script_helper.py*
|
%exclude %{pylibdir}/test/script_helper.py*
|
||||||
@ -616,6 +639,15 @@ sed -e "s|LIBRARY_PATH|%{_libdir}/%{py_INSTSONAME_debug}|" %{SOURCE1} \
|
|||||||
%{dynload_dir}/_testcapimodule_d.so
|
%{dynload_dir}/_testcapimodule_d.so
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Dec 25 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.7.16-8
|
||||||
|
- exclude private key; provide some file in python2-devel
|
||||||
|
|
||||||
|
* Sat Dec 21 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.7.16-7
|
||||||
|
- Type:bugfix
|
||||||
|
- Id:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:fix CVE
|
||||||
|
|
||||||
* Thu Nov 28 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.7.16-6
|
* Thu Nov 28 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.7.16-6
|
||||||
- add _pyconfig32_h _pyconfig64_h global var
|
- add _pyconfig32_h _pyconfig64_h global var
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user