8000 gh-119511: Fix OOM vulnerability in imaplib · serhiy-storchaka/cpython@6322049 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6322049

Browse files
pythongh-119511: Fix OOM vulnerability in imaplib
The IMAP4 client could consume an arbitrary amount of memory when trying to connent to a malicious server, because it read a "literal" data with a single read(size) call, and BufferedReader.read() allocates the bytes object of the specified size before reading. Now the IMAP4 client reads data by chunks, therefore the amount of used memory is limited by the amount of the data actually been sent by the server.
1 parent b48a3db commit 6322049

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

Lib/imaplib.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
# search command can be quite large, so we now use 1M.
5353
_MAXLINE = 1000000
5454

55+
# Data larger than this will be read in chunks, to prevent extreme
56+
# overallocation.
57+
_SAFE_BUF_SIZE = 1 << 20
5558

5659
# Commands
5760

@@ -315,6 +318,13 @@ def open(self, host='', port=IMAP4_PORT, timeout=None):
315318

316319
def read(self, size):
317320
"""Read 'size' bytes from remote."""
321+
cursize = min(size, _SAFE_BUF_SIZE)
322+
data = self.file.read(cursize)
323+
while cursize < size and len(data) == cursize:
324+
delta = min(cursize, size - cursize)
325+
data += self.file.read(delta)
326+
cursize += delta
327+
return data
318328
return self.file.read(size)
319329

320330

Lib/test/test_imaplib.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,18 @@ def handle(self):
907907
self.assertRaises(imaplib.IMAP4.error,
908908
self.imap_class, *server.server_address)
909909

910+
def test_truncated_large_literal(self):
911+
class BadHandler(SimpleIMAPHandler):
912+
def handle(self):
913+
self._send_textline('* OK {%d}' % size)
914+
self._send_textline('IMAP4rev1')
915+
916+
for w in range(15, 64):
917+
size = 1 << w
918+
with self.reaped_server(BadHandler) as server:
919+
self.assertRaises(imaplib.IMAP4.abort,
920+
self.imap_class, *server.server_address)
921+
910922
@threading_helper.reap_threads
911923
def test_simple_with_statement(self):
912924
# simplest call
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a vulnerability in the :mod:`imaplib` module, when connecting to a
2+
malicious server could cause an arbitrary amount of memory to be consumed.

0 commit comments

Comments
 (0)
0