|
|
f63228 |
|
|
|
f63228 |
# HG changeset patch
|
|
|
f63228 |
# User Barry Warsaw <barry@python.org>
|
|
|
f63228 |
# Date 1380582569 14400
|
|
|
f63228 |
# Node ID 36680a7c0e22686df9c338a9ca3cdb2c60e05b27
|
|
|
f63228 |
# Parent 0f5611bca5a284c0b5f978e83a05818f0907bda8# Parent 731abf7834c43efb321231e65e7dd76ad9e8e661
|
|
|
f63228 |
- Issue #16040: CVE-2013-1752: nntplib: Limit maximum line lengths to 2048 to
|
|
|
f63228 |
prevent readline() calls from consuming too much memory. Patch by Jyrki
|
|
|
f63228 |
Pulliainen.
|
|
|
f63228 |
|
|
|
f63228 |
diff --git a/Lib/nntplib.py b/Lib/nntplib.py
|
|
|
f63228 |
--- a/Lib/nntplib.py
|
|
|
f63228 |
+++ b/Lib/nntplib.py
|
|
|
f63228 |
@@ -37,6 +37,13 @@ import socket
|
|
|
f63228 |
"error_reply","error_temp","error_perm","error_proto",
|
|
|
f63228 |
"error_data",]
|
|
|
f63228 |
|
|
|
f63228 |
+# maximal line length when calling readline(). This is to prevent
|
|
|
f63228 |
+# reading arbitrary lenght lines. RFC 3977 limits NNTP line length to
|
|
|
f63228 |
+# 512 characters, including CRLF. We have selected 2048 just to be on
|
|
|
f63228 |
+# the safe side.
|
|
|
f63228 |
+_MAXLINE = 2048
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
# Exceptions raised when an error or invalid response is received
|
|
|
f63228 |
class NNTPError(Exception):
|
|
|
f63228 |
"""Base class for all nntplib exceptions"""
|
|
|
f63228 |
@@ -200,7 +207,9 @@ class NNTP:
|
|
|
f63228 |
def getline(self):
|
|
|
f63228 |
"""Internal: return one line from the server, stripping CRLF.
|
|
|
f63228 |
Raise EOFError if the connection is closed."""
|
|
|
f63228 |
- line = self.file.readline()
|
|
|
f63228 |
+ line = self.file.readline(_MAXLINE + 1)
|
|
|
f63228 |
+ if len(line) > _MAXLINE:
|
|
|
f63228 |
+ raise NNTPDataError('line too long')
|
|
|
f63228 |
if self.debugging > 1:
|
|
|
f63228 |
print '*get*', repr(line)
|
|
|
f63228 |
if not line: raise EOFError
|
|
|
f63228 |
diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py
|
|
|
f63228 |
new file mode 100644
|
|
|
f63228 |
--- /dev/null
|
|
|
f63228 |
+++ b/Lib/test/test_nntplib.py
|
|
|
f63228 |
@@ -0,0 +1,65 @@
|
|
|
f63228 |
+import socket
|
|
|
f63228 |
+import threading
|
|
|
f63228 |
+import nntplib
|
|
|
f63228 |
+import time
|
|
|
f63228 |
+
|
|
|
f63228 |
+from unittest import TestCase
|
|
|
f63228 |
+from test import test_support
|
|
|
f63228 |
+
|
|
|
f63228 |
+HOST = test_support.HOST
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+def server(evt, serv, evil=False):
|
|
|
f63228 |
+ serv.listen(5)
|
|
|
f63228 |
+ try:
|
|
|
f63228 |
+ conn, addr = serv.accept()
|
|
|
f63228 |
+ except socket.timeout:
|
|
|
f63228 |
+ pass
|
|
|
f63228 |
+ else:
|
|
|
f63228 |
+ if evil:
|
|
|
f63228 |
+ conn.send("1 I'm too long response" * 3000 + "\n")
|
|
|
f63228 |
+ else:
|
|
|
f63228 |
+ conn.send("1 I'm OK response\n")
|
|
|
f63228 |
+ conn.close()
|
|
|
f63228 |
+ finally:
|
|
|
f63228 |
+ serv.close()
|
|
|
f63228 |
+ evt.set()
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+class BaseServerTest(TestCase):
|
|
|
f63228 |
+ def setUp(self):
|
|
|
f63228 |
+ self.evt = threading.Event()
|
|
|
f63228 |
+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
f63228 |
+ self.sock.settimeout(3)
|
|
|
f63228 |
+ self.port = test_support.bind_port(self.sock)
|
|
|
f63228 |
+ threading.Thread(
|
|
|
f63228 |
+ target=server,
|
|
|
f63228 |
+ args=(self.evt, self.sock, self.evil)).start()
|
|
|
f63228 |
+ time.sleep(.1)
|
|
|
f63228 |
+
|
|
|
f63228 |
+ def tearDown(self):
|
|
|
f63228 |
+ self.evt.wait()
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+class ServerTests(BaseServerTest):
|
|
|
f63228 |
+ evil = False
|
|
|
f63228 |
+
|
|
|
f63228 |
+ def test_basic_connect(self):
|
|
|
f63228 |
+ nntp = nntplib.NNTP('localhost', self.port)
|
|
|
f63228 |
+ nntp.sock.close()
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+class EvilServerTests(BaseServerTest):
|
|
|
f63228 |
+ evil = True
|
|
|
f63228 |
+
|
|
|
f63228 |
+ def test_too_long_line(self):
|
|
|
f63228 |
+ self.assertRaises(nntplib.NNTPDataError,
|
|
|
f63228 |
+ nntplib.NNTP, 'localhost', self.port)
|
|
|
f63228 |
+
|
|
|
f63228 |
+
|
|
|
f63228 |
+def test_main(verbose=None):
|
|
|
f63228 |
+ test_support.run_unittest(EvilServerTests)
|
|
|
f63228 |
+ test_support.run_unittest(ServerTests)
|
|
|
f63228 |
+
|
|
|
f63228 |
+if __name__ == '__main__':
|
|
|
f63228 |
+ test_main()
|