An interpreted, interactive, object-oriented programming language
CentOS Sources
2017-08-01 71084d584ff953f5463757ec6536406320560b4d
commit | author | age
f63228 1
CS 2 # HG changeset patch
3 # User Barry Warsaw <barry@python.org>
4 # Date 1380582569 14400
5 # Node ID 36680a7c0e22686df9c338a9ca3cdb2c60e05b27
6 # Parent  0f5611bca5a284c0b5f978e83a05818f0907bda8# Parent  731abf7834c43efb321231e65e7dd76ad9e8e661
7 - Issue #16040: CVE-2013-1752: nntplib: Limit maximum line lengths to 2048 to
8   prevent readline() calls from consuming too much memory.  Patch by Jyrki
9   Pulliainen.
10
11 diff --git a/Lib/nntplib.py b/Lib/nntplib.py
12 --- a/Lib/nntplib.py
13 +++ b/Lib/nntplib.py
14 @@ -37,6 +37,13 @@ import socket
15             "error_reply","error_temp","error_perm","error_proto",
16             "error_data",]
17  
18 +# maximal line length when calling readline(). This is to prevent
19 +# reading arbitrary lenght lines. RFC 3977 limits NNTP line length to
20 +# 512 characters, including CRLF. We have selected 2048 just to be on
21 +# the safe side.
22 +_MAXLINE = 2048
23 +
24 +
25  # Exceptions raised when an error or invalid response is received
26  class NNTPError(Exception):
27      """Base class for all nntplib exceptions"""
28 @@ -200,7 +207,9 @@ class NNTP:
29      def getline(self):
30          """Internal: return one line from the server, stripping CRLF.
31          Raise EOFError if the connection is closed."""
32 -        line = self.file.readline()
33 +        line = self.file.readline(_MAXLINE + 1)
34 +        if len(line) > _MAXLINE:
35 +            raise NNTPDataError('line too long')
36          if self.debugging > 1:
37              print '*get*', repr(line)
38          if not line: raise EOFError
39 diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py
40 new file mode 100644
41 --- /dev/null
42 +++ b/Lib/test/test_nntplib.py
43 @@ -0,0 +1,65 @@
44 +import socket
45 +import threading
46 +import nntplib
47 +import time
48 +
49 +from unittest import TestCase
50 +from test import test_support
51 +
52 +HOST = test_support.HOST
53 +
54 +
55 +def server(evt, serv, evil=False):
56 +    serv.listen(5)
57 +    try:
58 +        conn, addr = serv.accept()
59 +    except socket.timeout:
60 +        pass
61 +    else:
62 +        if evil:
63 +            conn.send("1 I'm too long response" * 3000 + "\n")
64 +        else:
65 +            conn.send("1 I'm OK response\n")
66 +        conn.close()
67 +    finally:
68 +        serv.close()
69 +        evt.set()
70 +
71 +
72 +class BaseServerTest(TestCase):
73 +    def setUp(self):
74 +        self.evt = threading.Event()
75 +        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
76 +        self.sock.settimeout(3)
77 +        self.port = test_support.bind_port(self.sock)
78 +        threading.Thread(
79 +            target=server,
80 +            args=(self.evt, self.sock, self.evil)).start()
81 +        time.sleep(.1)
82 +
83 +    def tearDown(self):
84 +        self.evt.wait()
85 +
86 +
87 +class ServerTests(BaseServerTest):
88 +    evil = False
89 +
90 +    def test_basic_connect(self):
91 +        nntp = nntplib.NNTP('localhost', self.port)
92 +        nntp.sock.close()
93 +
94 +
95 +class EvilServerTests(BaseServerTest):
96 +    evil = True
97 +
98 +    def test_too_long_line(self):
99 +        self.assertRaises(nntplib.NNTPDataError,
100 +                          nntplib.NNTP, 'localhost', self.port)
101 +
102 +
103 +def test_main(verbose=None):
104 +    test_support.run_unittest(EvilServerTests)
105 +    test_support.run_unittest(ServerTests)
106 +
107 +if __name__ == '__main__':
108 +    test_main()