--- /dev/null
+From b41cde823d026f2adc21ef14b1c2e92b1006de06 Mon Sep 17 00:00:00 2001
+From: Dong-hee Na <donghee.na92@gmail.com>
+Date: Sat, 28 Sep 2019 10:17:25 +0900
+Subject: [PATCH 1/3] [2.7] bpo-38243: Escape the server title of
+ DocXMLRPCServer when rendering
+
+---
+ Lib/DocXMLRPCServer.py | 10 +++++++++-
+ Lib/test/test_docxmlrpc.py | 20 +++++++++++++++++++
+ .../2019-09-25-13-21-09.bpo-38243.1pfz24.rst | 3 +++
+ 3 files changed, 32 insertions(+), 1 deletion(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst
+
+diff --git a/Lib/DocXMLRPCServer.py b/Lib/DocXMLRPCServer.py
+index 4064ec2e48d4d..a0e407b6318ad 100644
+--- a/Lib/DocXMLRPCServer.py
++++ b/Lib/DocXMLRPCServer.py
+@@ -210,7 +210,15 @@ def generate_html_documentation(self):
+ methods
+ )
+
+- return documenter.page(self.server_title, documentation)
++ escape_table = {
++ "&": "&",
++ '"': """,
++ "'": "'",
++ ">": ">",
++ "<": "<",
++ }
++ title = ''.join(escape_table.get(c, c) for c in self.server_title)
++ return documenter.page(title, documentation)
+
+ class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
+ """XML-RPC and documentation request handler class.
+diff --git a/Lib/test/test_docxmlrpc.py b/Lib/test/test_docxmlrpc.py
+index 4dff4159e2466..c45b892b8b3e7 100644
+--- a/Lib/test/test_docxmlrpc.py
++++ b/Lib/test/test_docxmlrpc.py
+@@ -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,25 @@ def test_autolink_dotted_methods(self):
+ 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 --git 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
+new file mode 100644
+index 0000000000000..8f02baed9ebe5
+--- /dev/null
++++ b/Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst
+@@ -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`.)
+
+From 00251ae0244cfae1f5a77d15f3d0415c12b65ada Mon Sep 17 00:00:00 2001
+From: Dong-hee Na <donghee.na92@gmail.com>
+Date: Tue, 1 Oct 2019 09:31:33 +0900
+Subject: [PATCH 2/3] bpo-38243:Refect victor's review
+
+---
+ Lib/DocXMLRPCServer.py | 20 ++++++++++++--------
+ 1 file changed, 12 insertions(+), 8 deletions(-)
+
+diff --git a/Lib/DocXMLRPCServer.py b/Lib/DocXMLRPCServer.py
+index a0e407b6318ad..6ab41c31b403e 100644
+--- a/Lib/DocXMLRPCServer.py
++++ b/Lib/DocXMLRPCServer.py
+@@ -20,6 +20,17 @@
+ CGIXMLRPCRequestHandler,
+ resolve_dotted_attribute)
+
++
++def _html_escape_quote(s, quote=True):
++ s = s.replace("&", "&") # Must be done first!
++ s = s.replace("<", "<")
++ s = s.replace(">", ">")
++ if quote:
++ s = s.replace('"', """)
++ s = s.replace('\'', "'")
++ return s
++
++
+ class ServerHTMLDoc(pydoc.HTMLDoc):
+ """Class used to generate pydoc HTML document for a server"""
+
+@@ -210,14 +221,7 @@ def generate_html_documentation(self):
+ methods
+ )
+
+- escape_table = {
+- "&": "&",
+- '"': """,
+- "'": "'",
+- ">": ">",
+- "<": "<",
+- }
+- title = ''.join(escape_table.get(c, c) for c in self.server_title)
++ title = _html_escape_quote(self.server_title)
+ return documenter.page(title, documentation)
+
+ class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
+
+From 09b17d8230a24586e417d52c332058f541d47999 Mon Sep 17 00:00:00 2001
+From: Dong-hee Na <donghee.na92@gmail.com>
+Date: Tue, 1 Oct 2019 19:35:34 +0900
+Subject: [PATCH 3/3] bpo-38243: Update
+
+---
+ Lib/DocXMLRPCServer.py | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/Lib/DocXMLRPCServer.py b/Lib/DocXMLRPCServer.py
+index 6ab41c31b403e..90b037dd35d6b 100644
+--- a/Lib/DocXMLRPCServer.py
++++ b/Lib/DocXMLRPCServer.py
+@@ -21,13 +21,12 @@
+ resolve_dotted_attribute)
+
+
+-def _html_escape_quote(s, quote=True):
++def _html_escape_quote(s):
+ s = s.replace("&", "&") # Must be done first!
+ s = s.replace("<", "<")
+ s = s.replace(">", ">")
+- if quote:
+- s = s.replace('"', """)
+- s = s.replace('\'', "'")
++ s = s.replace('"', """)
++ s = s.replace('\'', "'")
+ return s
+
+
--- /dev/null
+From c2828900ec85e1e2957016e1e078de3a9677a963 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Roberto=20C=2E=20S=C3=A1nchez?= <roberto@connexer.com>
+Date: Tue, 10 Sep 2019 21:48:34 -0400
+Subject: [PATCH] [2.7] bpo-34155: Dont parse domains containing @ (GH-13079)
+
+https://bugs.python.org/issue34155
+(cherry picked from commit 8cb65d1381b027f0b09ee36bfed7f35bb4dec9a9)
+
+Excludes changes to Lib/email/_header_value_parser.py, which did not
+exist in 2.7.
+
+Co-authored-by: jpic <jpic@users.noreply.github.com>
+---
+ Lib/email/_parseaddr.py | 11 ++++++++++-
+ Lib/email/test/test_email.py | 14 ++++++++++++++
+ .../2019-05-04-13-33-37.bpo-34155.MJll68.rst | 1 +
+ 3 files changed, 25 insertions(+), 1 deletion(-)
+ create mode 100644 Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
+
+diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py
+index 690db2c22d34d..dc49d2e45a5eb 100644
+--- a/Lib/email/_parseaddr.py
++++ b/Lib/email/_parseaddr.py
+@@ -336,7 +336,12 @@ def getaddrspec(self):
+ 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 @@ def getdomain(self):
+ 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 --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py
+index 4b4dee3d34644..2efe44ac5a73f 100644
+--- a/Lib/email/test/test_email.py
++++ b/Lib/email/test/test_email.py
+@@ -2306,6 +2306,20 @@ def test_parseaddr_empty(self):
+ 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 --git 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
+new file mode 100644
+index 0000000000000..50292e29ed1d2
+--- /dev/null
++++ b/Misc/NEWS.d/next/Security/2019-05-04-13-33-37.bpo-34155.MJll68.rst
+@@ -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.