diff -r 034e1e076c77 Lib/ftplib.py --- a/Lib/ftplib.py Sun Jan 20 12:18:34 2013 +0200 +++ b/Lib/ftplib.py Tue Feb 05 21:28:30 2013 +0100 @@ -59,6 +59,11 @@ class error_proto(Error): pass # response does not begin with [1-5] +class LineTooLong(Error): + def __init__(self): + Error.__init__(self, "got more than %d bytes" % _MAXLINE) + + # All exceptions (hopefully) that may be raised here and that aren't # (always) programming errors on our side all_errors = (Error, OSError, EOFError) @@ -67,6 +72,7 @@ # Line terminators (we always output CRLF, but accept any of CRLF, CR, LF) CRLF = '\r\n' B_CRLF = b'\r\n' +_MAXLINE = 65536 # The class itself class FTP: @@ -194,7 +200,9 @@ # Internal: return one line from the server, stripping CRLF. # Raise EOFError if the connection is closed def getline(self): - line = self.file.readline() + line = self.file.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong() if self.debugging > 1: print('*get*', self.sanitize(line)) if not line: raise EOFError @@ -446,7 +454,9 @@ with self.transfercmd(cmd) as conn, \ conn.makefile('r', encoding=self.encoding) as fp: while 1: - line = fp.readline() + line = fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong() if self.debugging > 2: print('*retr*', repr(line)) if not line: break @@ -496,7 +506,9 @@ self.voidcmd('TYPE A') with self.transfercmd(cmd) as conn: while 1: - buf = fp.readline() + buf = fp.readline(_MAXLINE + 1) + if len(buf) > _MAXLINE: + raise LineTooLong() if not buf: break if buf[-2:] != B_CRLF: if buf[-1] in B_CRLF: buf = buf[:-1] @@ -773,7 +785,9 @@ fp = conn.makefile('r', encoding=self.encoding) with fp, conn: while 1: - line = fp.readline() + line = fp.readline(_MAXLINE + 1) + if len(line) > _MAXLINE: + raise LineTooLong() if self.debugging > 2: print('*retr*', repr(line)) if not line: break diff -r 034e1e076c77 Lib/test/test_ftplib.py --- a/Lib/test/test_ftplib.py Sun Jan 20 12:18:34 2013 +0200 +++ b/Lib/test/test_ftplib.py Tue Feb 05 21:28:30 2013 +0100 @@ -224,6 +224,16 @@ self.dtp.close_when_done() self.rest = None + def cmd_retrlarge(self, arg): + self.push('125 retr ok') + if self.rest is not None: + offset = int(self.rest) + else: + offset = 0 + self.dtp.push("k" * 65537) + self.dtp.close_when_done() + self.rest = None + def cmd_list(self, arg): self.push('125 list ok') self.dtp.push(LIST_DATA) @@ -560,6 +570,9 @@ received = [] self.client.retrlines('retr', received.append) self.check_data(''.join(received), RETR_DATA.replace('\r\n', '')) + self.assertRaises(ftplib.LineTooLong, + self.client.retrlines, + ('retrlarge')) def test_storbinary(self): f = io.BytesIO(RETR_DATA.encode('ascii')) diff -r 034e1e076c77 Misc/ACKS --- a/Misc/ACKS Sun Jan 20 12:18:34 2013 +0200 +++ b/Misc/ACKS Tue Feb 05 21:28:30 2013 +0100 @@ -564,6 +564,7 @@ Jack Jansen Bill Janssen Thomas Jarosch +Michał Jastrzębski Juhana Jauhiainen Zbigniew Jędrzejewski-Szmek Julien Jehannet