sync community bugfix patches

This commit is contained in:
shixuantong 2022-02-19 11:26:40 +08:00
parent 6f1ffbd1fe
commit ef6501552c
6 changed files with 474 additions and 1 deletions

View File

@ -0,0 +1,128 @@
From d2cc04cd3024869101e894f73307944d98d187c8 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 30 Aug 2021 12:16:24 -0700
Subject: [PATCH] [3.7] bpo-43124: Fix smtplib multiple CRLF injection
(GH-25987) (GH-28037)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Miguel Brito <5544985+miguendes@users.noreply.github.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
(cherry picked from commit 0897253f426068ea6a6fbe0ada01689af9ef1019)
---
Lib/smtplib.py | 11 +++--
Lib/test/test_smtplib.py | 55 ++++++++++++++++++++++
.../2021-05-08-11-50-46.bpo-43124.2CTM6M.rst | 2 +
3 files changed, 65 insertions(+), 3 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2021-05-08-11-50-46.bpo-43124.2CTM6M.rst
diff --git a/Lib/smtplib.py b/Lib/smtplib.py
index 22d5097..345f03d 100755
--- a/Lib/smtplib.py
+++ b/Lib/smtplib.py
@@ -361,10 +361,15 @@ def send(self, s):
def putcmd(self, cmd, args=""):
"""Send a command to the server."""
if args == "":
- str = '%s%s' % (cmd, CRLF)
+ s = cmd
else:
- str = '%s %s%s' % (cmd, args, CRLF)
- self.send(str)
+ s = f'{cmd} {args}'
+ if '\r' in s or '\n' in s:
+ s = s.replace('\n', '\\n').replace('\r', '\\r')
+ raise ValueError(
+ f'command and arguments contain prohibited newline characters: {s}'
+ )
+ self.send(f'{s}{CRLF}')
def getreply(self):
"""Get a reply from the server.
diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
index b4149d3..a8c7402 100644
--- a/Lib/test/test_smtplib.py
+++ b/Lib/test/test_smtplib.py
@@ -282,6 +282,16 @@ def testEXPNNotImplemented(self):
self.assertEqual(smtp.getreply(), expected)
smtp.quit()
+ def test_issue43124_putcmd_escapes_newline(self):
+ # see: https://bugs.python.org/issue43124
+ smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost',
+ timeout=10) # support.LOOPBACK_TIMEOUT in newer Pythons
+ self.addCleanup(smtp.close)
+ with self.assertRaises(ValueError) as exc:
+ smtp.putcmd('helo\nX-INJECTED')
+ self.assertIn("prohibited newline characters", str(exc.exception))
+ smtp.quit()
+
def testVRFY(self):
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3)
expected = (252, b'Cannot VRFY user, but will accept message ' + \
@@ -351,6 +361,51 @@ def testSendNeedingDotQuote(self):
mexpect = '%s%s\n%s' % (MSG_BEGIN, m, MSG_END)
self.assertEqual(self.output.getvalue(), mexpect)
+ def test_issue43124_escape_localhostname(self):
+ # see: https://bugs.python.org/issue43124
+ # connect and send mail
+ m = 'wazzuuup\nlinetwo'
+ smtp = smtplib.SMTP(HOST, self.port, local_hostname='hi\nX-INJECTED',
+ timeout=10) # support.LOOPBACK_TIMEOUT in newer Pythons
+ self.addCleanup(smtp.close)
+ with self.assertRaises(ValueError) as exc:
+ smtp.sendmail("hi@me.com", "you@me.com", m)
+ self.assertIn(
+ "prohibited newline characters: ehlo hi\\nX-INJECTED",
+ str(exc.exception),
+ )
+ # XXX (see comment in testSend)
+ time.sleep(0.01)
+ smtp.quit()
+
+ debugout = smtpd.DEBUGSTREAM.getvalue()
+ self.assertNotIn("X-INJECTED", debugout)
+
+ def test_issue43124_escape_options(self):
+ # see: https://bugs.python.org/issue43124
+ # connect and send mail
+ m = 'wazzuuup\nlinetwo'
+ smtp = smtplib.SMTP(
+ HOST, self.port, local_hostname='localhost',
+ timeout=10) # support.LOOPBACK_TIMEOUT in newer Pythons
+
+ self.addCleanup(smtp.close)
+ smtp.sendmail("hi@me.com", "you@me.com", m)
+ with self.assertRaises(ValueError) as exc:
+ smtp.mail("hi@me.com", ["X-OPTION\nX-INJECTED-1", "X-OPTION2\nX-INJECTED-2"])
+ msg = str(exc.exception)
+ self.assertIn("prohibited newline characters", msg)
+ self.assertIn("X-OPTION\\nX-INJECTED-1 X-OPTION2\\nX-INJECTED-2", msg)
+ # XXX (see comment in testSend)
+ time.sleep(0.01)
+ smtp.quit()
+
+ debugout = smtpd.DEBUGSTREAM.getvalue()
+ self.assertNotIn("X-OPTION", debugout)
+ self.assertNotIn("X-OPTION2", debugout)
+ self.assertNotIn("X-INJECTED-1", debugout)
+ self.assertNotIn("X-INJECTED-2", debugout)
+
def testSendNullSender(self):
m = 'A test message'
smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3)
diff --git a/Misc/NEWS.d/next/Security/2021-05-08-11-50-46.bpo-43124.2CTM6M.rst b/Misc/NEWS.d/next/Security/2021-05-08-11-50-46.bpo-43124.2CTM6M.rst
new file mode 100644
index 0000000..e897d6c
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2021-05-08-11-50-46.bpo-43124.2CTM6M.rst
@@ -0,0 +1,2 @@
+Made the internal ``putcmd`` function in :mod:`smtplib` sanitize input for
+presence of ``\r`` and ``\n`` characters to avoid (unlikely) command injection.
--
1.8.3.1

View File

@ -0,0 +1,59 @@
From 4fedd7123eaf147edd55eabbbd72e0bcc8368e47 Mon Sep 17 00:00:00 2001
From: Julien Palard <julien@palard.fr>
Date: Wed, 25 Nov 2020 10:23:17 +0100
Subject: [PATCH] bpo-12800: tarfile: Restore fix from 011525ee9 (GH-21409)
Restore fix from 011525ee92eb1c13ad1a62d28725a840e28f8160.
---
Lib/tarfile.py | 3 +++
Lib/test/test_tarfile.py | 6 +++---
Misc/NEWS.d/next/Library/2020-07-09-11-32-28.bpo-12800.fNgWwx.rst | 4 ++++
3 files changed, 10 insertions(+), 3 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2020-07-09-11-32-28.bpo-12800.fNgWwx.rst
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 3be5188..6d743da 100755
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -2201,6 +2201,9 @@ class TarFile(object):
try:
# For systems that support symbolic and hard links.
if tarinfo.issym():
+ if os.path.lexists(targetpath):
+ # Avoid FileExistsError on following os.symlink.
+ os.unlink(targetpath)
os.symlink(tarinfo.linkname, targetpath)
else:
# See extract().
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 9133d60..fe68c6f 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -1314,11 +1314,11 @@ class WriteTest(WriteTestBase, unittest.TestCase):
f.write('something\n')
os.symlink(source_file, target_file)
tar = tarfile.open(temparchive,'w')
- tar.add(source_file)
- tar.add(target_file)
+ tar.add(source_file, arcname="source")
+ tar.add(target_file, arcname="symlink")
tar.close()
# Let's extract it to the location which contains the symlink
- tar = tarfile.open(temparchive,'r')
+ tar = tarfile.open(temparchive,'r', errorlevel=2)
# this should not raise OSError: [Errno 17] File exists
try:
tar.extractall(path=tempdir)
diff --git a/Misc/NEWS.d/next/Library/2020-07-09-11-32-28.bpo-12800.fNgWwx.rst b/Misc/NEWS.d/next/Library/2020-07-09-11-32-28.bpo-12800.fNgWwx.rst
new file mode 100644
index 0000000..fdd7c5e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-09-11-32-28.bpo-12800.fNgWwx.rst
@@ -0,0 +1,4 @@
+Extracting a symlink from a tarball should succeed and overwrite the symlink
+if it already exists. The fix is to remove the existing file or symlink
+before extraction. Based on patch by Chris AtLee, Jeffrey Kintscher, and
+Senthil Kumaran.
--
1.8.3.1

View File

@ -0,0 +1,68 @@
From bfee9fad84531a471fd7864e88947320669f68e2 Mon Sep 17 00:00:00 2001
From: Peter McCormick <peter@pdmccormick.com>
Date: Sat, 19 Sep 2020 23:40:46 -0400
Subject: [PATCH] bpo-41815: SQLite: segfault if backup called on closed
database (GH-22322)
# [bpo-41815](): SQLite: fix segfault if backup called on closed database
Attempting to backup a closed database will trigger segfault:
```python
import sqlite3
target = sqlite3.connect(':memory:')
source = sqlite3.connect(':memory:')
source.close()
source.backup(target)
```
---
Lib/sqlite3/test/backup.py | 7 +++++++
Misc/NEWS.d/next/Library/2020-09-19-23-14-54.bpo-41815.RNpuX3.rst | 2 ++
Modules/_sqlite/connection.c | 4 ++++
3 files changed, 13 insertions(+)
create mode 100644 Misc/NEWS.d/next/Library/2020-09-19-23-14-54.bpo-41815.RNpuX3.rst
diff --git a/Lib/sqlite3/test/backup.py b/Lib/sqlite3/test/backup.py
index 903bacf..ad1da97 100644
--- a/Lib/sqlite3/test/backup.py
+++ b/Lib/sqlite3/test/backup.py
@@ -36,6 +36,13 @@ class BackupTests(unittest.TestCase):
with self.assertRaises(sqlite.ProgrammingError):
self.cx.backup(bck)
+ def test_bad_source_closed_connection(self):
+ bck = sqlite.connect(':memory:')
+ source = sqlite.connect(":memory:")
+ source.close()
+ with self.assertRaises(sqlite.ProgrammingError):
+ source.backup(bck)
+
def test_bad_target_in_transaction(self):
bck = sqlite.connect(':memory:')
bck.execute('CREATE TABLE bar (key INTEGER)')
diff --git a/Misc/NEWS.d/next/Library/2020-09-19-23-14-54.bpo-41815.RNpuX3.rst b/Misc/NEWS.d/next/Library/2020-09-19-23-14-54.bpo-41815.RNpuX3.rst
new file mode 100644
index 0000000..3560db9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-09-19-23-14-54.bpo-41815.RNpuX3.rst
@@ -0,0 +1,2 @@
+Fix SQLite3 segfault when backing up closed database. Patch contributed by
+Peter David McCormick.
diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
index 9eb61c1..2d2f4fd 100644
--- a/Modules/_sqlite/connection.c
+++ b/Modules/_sqlite/connection.c
@@ -1489,6 +1489,10 @@ pysqlite_connection_backup(pysqlite_Connection *self, PyObject *args, PyObject *
sleep_ms = (int)ms;
}
+ if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+ return NULL;
+ }
+
if (!pysqlite_check_connection((pysqlite_Connection *)target)) {
return NULL;
}
--
1.8.3.1

View File

@ -0,0 +1,105 @@
From 42d873c63aa9d160c132be4a34599531574db12c Mon Sep 17 00:00:00 2001
From: Andrew Svetlov <andrew.svetlov@gmail.com>
Date: Tue, 10 Nov 2020 15:58:31 +0200
Subject: [PATCH] bpo-42183: Fix a stack overflow error for asyncio Task or
Future repr() (GH-23020)
The overflow occurs under some circumstances when a task or future
recursively returns itself.
Co-authored-by: Kyle Stanley <aeros167@gmail.com>
---
Lib/asyncio/base_futures.py | 25 +++++++++++++++++++---
Lib/test/test_asyncio/test_futures2.py | 18 ++++++++++++++++
.../2020-10-29-11-17-35.bpo-42183.50ZcIi.rst | 4 ++++
3 files changed, 44 insertions(+), 3 deletions(-)
create mode 100644 Lib/test/test_asyncio/test_futures2.py
create mode 100644 Misc/NEWS.d/next/Library/2020-10-29-11-17-35.bpo-42183.50ZcIi.rst
diff --git a/Lib/asyncio/base_futures.py b/Lib/asyncio/base_futures.py
index 5182884..2646fde 100644
--- a/Lib/asyncio/base_futures.py
+++ b/Lib/asyncio/base_futures.py
@@ -2,6 +2,7 @@ __all__ = ()
import concurrent.futures._base
import reprlib
+from _thread import get_ident
from . import format_helpers
@@ -51,6 +52,16 @@ def _format_callbacks(cb):
return f'cb=[{cb}]'
+# bpo-42183: _repr_running is needed for repr protection
+# when a Future or Task result contains itself directly or indirectly.
+# The logic is borrowed from @reprlib.recursive_repr decorator.
+# Unfortunately, the direct decorator usage is impossible because of
+# AttributeError: '_asyncio.Task' object has no attribute '__module__' error.
+#
+# After fixing this thing we can return to the decorator based approach.
+_repr_running = set()
+
+
def _future_repr_info(future):
# (Future) -> str
"""helper function for Future.__repr__"""
@@ -59,9 +70,17 @@ def _future_repr_info(future):
if future._exception is not None:
info.append(f'exception={future._exception!r}')
else:
- # use reprlib to limit the length of the output, especially
- # for very long strings
- result = reprlib.repr(future._result)
+ key = id(future), get_ident()
+ if key in _repr_running:
+ result = '...'
+ else:
+ _repr_running.add(key)
+ try:
+ # use reprlib to limit the length of the output, especially
+ # for very long strings
+ result = reprlib.repr(future._result)
+ finally:
+ _repr_running.discard(key)
info.append(f'result={result}')
if future._callbacks:
info.append(_format_callbacks(future._callbacks))
diff --git a/Lib/test/test_asyncio/test_futures2.py b/Lib/test/test_asyncio/test_futures2.py
new file mode 100644
index 0000000..c78b0cb
--- /dev/null
+++ b/Lib/test/test_asyncio/test_futures2.py
@@ -0,0 +1,18 @@
+# IsolatedAsyncioTestCase based tests
+import asyncio
+import unittest
+
+
+class FutureTests(unittest.TestCase):
+ async def test_recursive_repr_for_pending_tasks(self):
+ # The call crashes if the guard for recursive call
+ # in base_futures:_future_repr_info is absent
+ # See Also: https://bugs.python.org/issue42183
+
+ async def func():
+ return asyncio.all_tasks()
+
+ # The repr() call should not raise RecursiveError at first.
+ # The check for returned string is not very reliable but
+ # exact comparison for the whole string is even weaker.
+ self.assertIn('...', repr(await asyncio.wait_for(func(), timeout=10)))
diff --git a/Misc/NEWS.d/next/Library/2020-10-29-11-17-35.bpo-42183.50ZcIi.rst b/Misc/NEWS.d/next/Library/2020-10-29-11-17-35.bpo-42183.50ZcIi.rst
new file mode 100644
index 0000000..f6d7653
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-10-29-11-17-35.bpo-42183.50ZcIi.rst
@@ -0,0 +1,4 @@
+Fix a stack overflow error for asyncio Task or Future repr().
+
+The overflow occurs under some circumstances when a Task or Future
+recursively returns itself.
--
1.8.3.1

View File

@ -0,0 +1,93 @@
From e9b85afd7dc004460f6d914375ab67d617a8a7ff Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Mon, 30 Aug 2021 11:48:04 -0700
Subject: [PATCH] bpo-45001: Make email date parsing more robust against
malformed input (GH-27946) (GH-27975)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Various date parsing utilities in the email module, such as
email.utils.parsedate(), are supposed to gracefully handle invalid
input, typically by raising an appropriate exception or by returning
None.
The internal email._parseaddr._parsedate_tz() helper used by some of
these date parsing routines tries to be robust against malformed input,
but unfortunately it can still crash ungracefully when a non-empty but
whitespace-only input is passed. This manifests as an unexpected
IndexError.
In practice, this can happen when parsing an email with only a newline
inside a Date: header, which unfortunately happens occasionally in the
real world.
Here's a minimal example:
$ python
Python 3.9.6 (default, Jun 30 2021, 10:22:16)
[GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import email.utils
>>> email.utils.parsedate('foo')
>>> email.utils.parsedate(' ')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.9/email/_parseaddr.py", line 176, in parsedate
t = parsedate_tz(data)
File "/usr/lib/python3.9/email/_parseaddr.py", line 50, in parsedate_tz
res = _parsedate_tz(data)
File "/usr/lib/python3.9/email/_parseaddr.py", line 72, in _parsedate_tz
if data[0].endswith(',') or data[0].lower() in _daynames:
IndexError: list index out of range
The fix is rather straight-forward: guard against empty lists, after
splitting on whitespace, but before accessing the first element.
(cherry picked from commit 989f6a3800f06b2bd31cfef7c3269a443ad94fac)
Co-authored-by: wouter bolsterlee <wouter@bolsterl.ee>
---
Lib/email/_parseaddr.py | 2 ++
Lib/test/test_email/test_email.py | 2 ++
Misc/NEWS.d/next/Library/2021-08-26-16-25-48.bpo-45001.tn_dKp.rst | 2 ++
3 files changed, 6 insertions(+)
create mode 100644 Misc/NEWS.d/next/Library/2021-08-26-16-25-48.bpo-45001.tn_dKp.rst
diff --git a/Lib/email/_parseaddr.py b/Lib/email/_parseaddr.py
index 41ff6f8..178329f 100644
--- a/Lib/email/_parseaddr.py
+++ b/Lib/email/_parseaddr.py
@@ -67,6 +67,8 @@ def _parsedate_tz(data):
if not data:
return
data = data.split()
+ if not data: # This happens for whitespace-only input.
+ return None
# The FWS after the comma after the day-of-week is optional, so search and
# adjust for this.
if data[0].endswith(',') or data[0].lower() in _daynames:
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index 9e5c6ad..64bcdcc 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -2967,6 +2967,8 @@ def test_formatdate_usegmt(self):
def test_parsedate_returns_None_for_invalid_strings(self):
self.assertIsNone(utils.parsedate(''))
self.assertIsNone(utils.parsedate_tz(''))
+ self.assertIsNone(utils.parsedate(' '))
+ self.assertIsNone(utils.parsedate_tz(' '))
self.assertIsNone(utils.parsedate('0'))
self.assertIsNone(utils.parsedate_tz('0'))
self.assertIsNone(utils.parsedate('A Complete Waste of Time'))
diff --git a/Misc/NEWS.d/next/Library/2021-08-26-16-25-48.bpo-45001.tn_dKp.rst b/Misc/NEWS.d/next/Library/2021-08-26-16-25-48.bpo-45001.tn_dKp.rst
new file mode 100644
index 0000000..55cc409
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2021-08-26-16-25-48.bpo-45001.tn_dKp.rst
@@ -0,0 +1,2 @@
+Made email date parsing more robust against malformed input, namely a
+whitespace-only ``Date:`` header. Patch by Wouter Bolsterlee.
--
1.8.3.1

View File

@ -3,7 +3,7 @@ Summary: Interpreter of the Python3 programming language
URL: https://www.python.org/
Version: 3.7.9
Release: 20
Release: 21
License: Python
%global branchversion 3.7
@ -154,6 +154,11 @@ Patch6044: backport-CVE-2021-3737.patch
Patch6045: backport-bpo-44022-Improve-the-regression-test.patch
Patch6046: backport-CVE-2021-4189.patch
Patch6047: backport-CVE-2022-0391.patch
Patch6048: backport-bpo-12800-tarfile-Restore-fix-from-011525ee9.patch
Patch6049: backport-bpo-42183-Fix-a-stack-overflow-error-for-asyncio-Tas.patch
Patch6050: backport-bpo-41815-SQLite-segfault-if-backup-called-on-closed.patch
Patch6051: backport-bpo-45001-Make-email-date-parsing-more-robust-agains.patch
Patch6052: backport-3.7-bpo-43124-Fix-smtplib-multiple-CRLF-injection-GH.patch
patch9000: Don-t-override-PYTHONPATH-which-is-already-set.patch
patch9001: add-the-sm3-method-for-obtaining-the-salt-value.patch
@ -296,6 +301,11 @@ rm Lib/ensurepip/_bundled/*.whl
%patch6045 -p1
%patch6046 -p1
%patch6047 -p1
%patch6048 -p1
%patch6049 -p1
%patch6050 -p1
%patch6051 -p1
%patch6052 -p1
%patch9000 -p1
%patch9001 -p1
@ -900,6 +910,16 @@ export BEP_GTDLIST="$BEP_GTDLIST_TMP"
%{_mandir}/*/*
%changelog
* Sat Feb 19 2022 shixuantong <shixuantong@h-partners.com> - 3.7.9-21
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:bpo-43124: Fix smtplib multiple CRLF injection
bpo-12800: tarfile: Restore fix from 011525ee9
bpo-41815: SQLite: segfault if backup called on closed database
bpo-42183: Fix a stack overflow error for asyncio Task or Future repr()
bpo-45001: Make email date parsing more robust against malformed input
* Thu Feb 17 2022 shixuantong <shixuantong@h-partners.com> - 3.7.9-20
- Type:CVE
- CVE:CVE-2021-4189 CVE-2022-0391