diff -r 034e1e076c77 Lib/ftplib.py --- a/Lib/ftplib.py Sun Jan 20 12:18:34 2013 +0200 +++ b/Lib/ftplib.py Sat Feb 09 17:49:51 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 = 8192 # 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 Sat Feb 09 17:49:51 2013 +0100 @@ -224,6 +224,12 @@ self.dtp.close_when_done() self.rest = None + def cmd_retrlarge(self, arg): + self.push('125 retr ok') + self.dtp.push("k" * 8193) + self.dtp.close_when_done() + self.rest = None + def cmd_list(self, arg): self.push('125 list ok') self.dtp.push(LIST_DATA) @@ -561,6 +567,11 @@ self.client.retrlines('retr', received.append) self.check_data(''.join(received), RETR_DATA.replace('\r\n', '')) + def test_retrlines_linetoolong(self): + self.assertRaises(ftplib.LineTooLong, + self.client.retrlines, + ('retrlarge')) + def test_storbinary(self): f = io.BytesIO(RETR_DATA.encode('ascii')) self.client.storbinary('stor', f) diff -r 034e1e076c77 Misc/ACKS --- a/Misc/ACKS Sun Jan 20 12:18:34 2013 +0200 +++ b/Misc/ACKS Sat Feb 09 17:49:51 2013 +0100 @@ -564,6 +564,7 @@ Jack Jansen Bill Janssen Thomas Jarosch +Michał Jastrzębski Juhana Jauhiainen Zbigniew Jędrzejewski-Szmek Julien Jehannet