diff -r 29ea3827cfaa Lib/ftplib.py --- a/Lib/ftplib.py Mon Dec 21 14:17:12 2015 -0600 +++ b/Lib/ftplib.py Thu Dec 24 11:41:07 2015 +0100 @@ -444,7 +444,12 @@ data = conn.recv(blocksize) if not data: break - callback(data) + try: + callback(data) + except Exception: + self.voidresp() + raise + # shutdown ssl layer if _SSLSocket is not None and isinstance(conn, _SSLSocket): conn.unwrap() @@ -479,7 +484,11 @@ line = line[:-2] elif line[-1:] == '\n': line = line[:-1] - callback(line) + try: + callback(line) + except Exception: + self.voidresp() + raise # shutdown ssl layer if _SSLSocket is not None and isinstance(conn, _SSLSocket): conn.unwrap() diff -r 29ea3827cfaa Lib/test/test_ftplib.py --- a/Lib/test/test_ftplib.py Mon Dec 21 14:17:12 2015 -0600 +++ b/Lib/test/test_ftplib.py Thu Dec 24 11:41:07 2015 +0100 @@ -573,6 +573,14 @@ self.client.retrlines('retr', received.append) self.check_data(''.join(received), RETR_DATA.replace('\r\n', '')) + def test_faulty_callback(self): + def callback(): + pass + self.assertRaises(Exception, self.client.retrbinary, 'retr', callback) + self.assertEqual(self.client.sendcmd('noop'), '200 noop ok') + self.assertRaises(Exception, self.client.retrlines, 'retr', callback) + self.assertEqual(self.client.sendcmd('noop'), '200 noop ok') + def test_storbinary(self): f = io.BytesIO(RETR_DATA.encode('ascii')) self.client.storbinary('stor', f)