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