Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c545a5e

Browse files
committed
- Issue python#16041: CVE-2013-1752: poplib: Limit maximum line lengths to 2048 to
prevent readline() calls from consuming too much member. Patch by Jyrki Pulliainen.
1 parent 6c1bb7b commit c545a5e

File tree

3 files changed

+95
-7
lines changed

3 files changed

+95
-7
lines changed

Lib/poplib.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class error_proto(Exception): pass
3232
LF = '\n'
3333
CRLF = CR+LF
3434

35+
# maximal line length when calling readline(). This is to prevent
36+
# reading arbitrary lenght lines. RFC 1939 limits POP3 line length to
37+
# 512 characters, including CRLF. We have selected 2048 just to be on
38+
# the safe side.
39+
_MAXLINE = 2048
40+
3541

3642
class POP3:
3743

@@ -103,7 +109,10 @@ def _putcmd(self, line):
103109
# Raise error_proto('-ERR EOF') if the connection is closed.
104110

105111
def _getline(self):
106-
line = self.file.readline()
112+
line = self.file.readline(_MAXLINE + 1)
113+
if len(line) > _MAXLINE:
114+
raise error_proto('line too long')
115+
107116
if self._debugging > 1: print '*get*', repr(line)
108117
if not line: raise error_proto('-ERR EOF')
109118
octets = len(line)
@@ -363,7 +372,10 @@ def _getline(self):
363372
line = ""
364373
renewline = re.compile(r'.*?\n')
365374
match = renewline.match(self.buffer)
375+
366376
while not match:
377+
if len(self.buffer) > _MAXLINE:
378+
raise error_proto('line too long')
367379
self._fillBuffer()
368380
match = renewline.match(self.buffer)
369381
line = match.group(0)

Lib/test/test_poplib.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import socket
23
import threading
34
import poplib
@@ -21,6 +22,34 @@ def server(evt, serv):
2122
serv.close()
2223
evt.set()
2324

25+
26+
def evil_server(evt, serv, use_ssl=False):
27+
serv.listen(5)
28+
try:
29+
conn, addr = serv.accept()
30+
if use_ssl:
31+
conn = ssl.wrap_socket(
32+
conn,
33+
server_side=True,
34+
certfile=CERTFILE,
35+
)
36+
except socket.timeout:
37+
pass
38+
else:
39+
if use_ssl:
40+
try:
41+
conn.do_handshake()
42+
except ssl.SSLError, err:
43+
if err.args[0] not in (ssl.SSL_ERROR_WANT_READ,
44+
ssl.SSL_ERROR_WANT_WRITE):
45+
raise
46+
conn.send("+ Hola mundo" * 1000 + "\n")
47+
conn.close()
48+
finally:
49+
serv.close()
50+
evt.set()
51+
52+
2453
class GeneralTests(TestCase):
2554

2655
def setUp(self):
@@ -65,8 +94,50 @@ def testTimeoutValue(self):
6594
pop.sock.close()
6695

6796

97+
class EvilServerTests(TestCase):
98+
use_ssl = False
99+
100+
def setUp(self):
101+
self.evt = threading.Event()
102+
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
103+
self.sock.settimeout(3)
104+
self.port = test_support.bind_port(self.sock)
105+
threading.Thread(
106+
target=evil_server,
107+
args=(self.evt, self.sock, self.use_ssl)).start()
108+
time.sleep(.1)
109+
110+
def tearDown(self):
111+
self.evt.wait()
112+
113+
def testTooLongLines(self):
114+
self.assertRaises(poplib.error_proto, poplib.POP3,
115+
'localhost', self.port, timeout=30)
116+
117+
118+
SUPPORTS_SSL = False
119+
120+
if hasattr(poplib, 'POP3_SSL'):
121+
import ssl
122+
123+
SUPPORTS_SSL = True
124+
CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir,
125+
"keycert.pem")
126+
127+
class EvilSSLServerTests(EvilServerTests):
128+
use_ssl = True
129+
130+
def testTooLongLines(self):
131+
self.assertRaises(poplib.error_proto, poplib.POP3_SSL,
132+
'localhost', self.port)
133+
134+
68135
def test_main(verbose=None):
69136
test_support.run_unittest(GeneralTests)
137+
test_support.run_unittest(EvilServerTests)
138+
139+
if SUPPORTS_SSL:
140+
test_support.run_unittest(EvilSSLServerTests)
70141

71142
if __name__ == '__main__':
72143
test_main()

Misc/NEWS

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,22 @@ Core and Builtins
1313
Library
1414
-------
1515

16-
- Issue #16037: HTTPMessage.readheaders() raises an HTTPException when more
17-
than 100 headers are read. Adapted from patch by Jyrki Pulliainen.
16+
- Issue #16042: CVE-2013-1752: smtplib: Limit amount of data read by
17+
limiting the call to readline(). Original patch by Christian Heimes.
18+
19+
- Issue #16041: CVE-2013-1752: poplib: Limit maximum line lengths to 2048 to
20+
prevent readline() calls from consuming too much member. Patch by Jyrki
21+
Pulliainen.
22+
23+
- Issue #16039: CVE-2013-1752: Change use of readline in imaplib module to
24+
limit line length. Patch by Emil Lind.
1825

1926
- Issue #16038: CVE-2013-1752: ftplib: Limit amount of data read by
2027
limiting the call to readline(). Original patch by Michał
2128
Jastrzębski and Giampaolo Rodola.
2229

23-
- Issue #16039: CVE-2013-1752: Change use of readline in imaplib module to
24-
limit line length. Patch by Emil Lind.
30+
- Issue #16037: HTTPMessage.readheaders() raises an HTTPException when more
31+
than 100 headers are read. Adapted from patch by Jyrki Pulliainen.
2532

2633
- Issue #14984: On POSIX systems, when netrc is called without a filename
2734
argument (and therefore is reading the user's $HOME/.netrc file), it now
@@ -32,8 +39,6 @@ Library
3239
- Issue #16248: Disable code execution from the user's home directory by
3340
tkinter when the -E flag is passed to Python. Patch by Zachary Ware.
3441

35-
- Issue #16042: CVE-2013-1752: smtplib: Limit amount of data read by
36-
limiting the call to readline(). Original patch by Christian Heimes.
3742

3843
Extension Modules
3944
-----------------

0 commit comments

Comments
 (0)