From a28ef878a39e0dfb427f13d499608fdfdd9f3ed6 Mon Sep 17 00:00:00 2001 From: Mat Booth Date: Apr 23 2015 15:20:21 +0000 Subject: Update to release candidate 3 - Drop upstreamed patch for CVE-2013-1752 --- diff --git a/jython-CVE-2013-1752.patch b/jython-CVE-2013-1752.patch deleted file mode 100644 index 996973b..0000000 --- a/jython-CVE-2013-1752.patch +++ /dev/null @@ -1,471 +0,0 @@ -diff --git a/Lib/ftplib.py b/Lib/ftplib.py ---- a/Lib/ftplib.py -+++ b/Lib/ftplib.py -@@ -55,6 +55,8 @@ MSG_OOB = 0x1 - - # The standard FTP server control port - FTP_PORT = 21 -+# The sizehint parameter passed to readline() calls -+MAXLINE = 8192 - - - # Exception raised when an error or invalid response is received -@@ -101,6 +103,7 @@ class FTP: - debugging = 0 - host = '' - port = FTP_PORT -+ maxline = MAXLINE - sock = None - file = None - welcome = None -@@ -180,7 +183,9 @@ class FTP: - # 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(self.maxline + 1) -+ if len(line) > self.maxline: -+ raise Error("got more than %d bytes" % self.maxline) - if self.debugging > 1: - print '*get*', self.sanitize(line) - if not line: raise EOFError -@@ -432,7 +437,9 @@ class FTP: - conn = self.transfercmd(cmd) - fp = conn.makefile('rb') - while 1: -- line = fp.readline() -+ line = fp.readline(self.maxline + 1) -+ if len(line) > self.maxline: -+ raise Error("got more than %d bytes" % self.maxline) - if self.debugging > 2: print '*retr*', repr(line) - if not line: - break -@@ -485,7 +492,9 @@ class FTP: - self.voidcmd('TYPE A') - conn = self.transfercmd(cmd) - while 1: -- buf = fp.readline() -+ buf = fp.readline(self.maxline + 1) -+ if len(buf) > self.maxline: -+ raise Error("got more than %d bytes" % self.maxline) - if not buf: break - if buf[-2:] != CRLF: - if buf[-1] in CRLF: buf = buf[:-1] -@@ -710,7 +719,9 @@ else: - fp = conn.makefile('rb') - try: - while 1: -- line = fp.readline() -+ line = fp.readline(self.maxline + 1) -+ if len(line) > self.maxline: -+ raise Error("got more than %d bytes" % self.maxline) - if self.debugging > 2: print '*retr*', repr(line) - if not line: - break -@@ -748,7 +759,9 @@ else: - conn = self.transfercmd(cmd) - try: - while 1: -- buf = fp.readline() -+ buf = fp.readline(self.maxline + 1) -+ if len(buf) > self.maxline: -+ raise Error("got more than %d bytes" % self.maxline) - if not buf: break - if buf[-2:] != CRLF: - if buf[-1] in CRLF: buf = buf[:-1] -@@ -905,7 +918,9 @@ class Netrc: - fp = open(filename, "r") - in_macro = 0 - while 1: -- line = fp.readline() -+ line = fp.readline(self.maxline + 1) -+ if len(line) > self.maxline: -+ raise Error("got more than %d bytes" % self.maxline) - if not line: break - if in_macro and line.strip(): - macro_lines.append(line) -diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py ---- a/Lib/test/test_ftplib.py -+++ b/Lib/test/test_ftplib.py -@@ -65,6 +65,7 @@ class DummyFTPHandler(asynchat.async_cha - self.last_received_data = '' - self.next_response = '' - self.rest = None -+ self.next_retr_data = RETR_DATA - self.push('220 welcome') - - def collect_incoming_data(self, data): -@@ -189,7 +190,7 @@ class DummyFTPHandler(asynchat.async_cha - offset = int(self.rest) - else: - offset = 0 -- self.dtp.push(RETR_DATA[offset:]) -+ self.dtp.push(self.next_retr_data[offset:]) - self.dtp.close_when_done() - self.rest = None - -@@ -203,6 +204,11 @@ class DummyFTPHandler(asynchat.async_cha - self.dtp.push(NLST_DATA) - self.dtp.close_when_done() - -+ def cmd_setlongretr(self, arg): -+ # For testing. Next RETR will return long line. -+ self.next_retr_data = 'x' * int(arg) -+ self.push('125 setlongretr ok') -+ - - class DummyFTPServer(asyncore.dispatcher, threading.Thread): - -@@ -558,6 +564,20 @@ class TestFTPClass(TestCase): - # IPv4 is in use, just make sure send_epsv has not been used - self.assertEqual(self.server.handler.last_received_cmd, 'pasv') - -+ def test_line_too_long(self): -+ self.assertRaises(ftplib.Error, self.client.sendcmd, -+ 'x' * self.client.maxline * 2) -+ -+ def test_retrlines_too_long(self): -+ self.client.sendcmd('SETLONGRETR %d' % (self.client.maxline * 2)) -+ received = [] -+ self.assertRaises(ftplib.Error, -+ self.client.retrlines, 'retr', received.append) -+ -+ def test_storlines_too_long(self): -+ f = StringIO.StringIO('x' * self.client.maxline * 2) -+ self.assertRaises(ftplib.Error, self.client.storlines, 'stor', f) -+ - - class TestIPv6Environment(TestCase): - -diff --git a/Lib/imaplib.py b/Lib/imaplib.py ---- a/Lib/imaplib.py -+++ b/Lib/imaplib.py -@@ -35,6 +35,15 @@ IMAP4_PORT = 143 - IMAP4_SSL_PORT = 993 - AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first - -+# Maximal line length when calling readline(). This is to prevent -+# reading arbitrary length lines. RFC 3501 and 2060 (IMAP 4rev1) -+# don't specify a line length. RFC 2683 however suggests limiting client -+# command lines to 1000 octets and server command lines to 8000 octets. -+# We have selected 10000 for some extra margin and since that is supposedly -+# also what UW and Panda IMAP does. -+_MAXLINE = 10000 -+ -+ - # Commands - - Commands = { -@@ -237,7 +246,10 @@ class IMAP4: - - def readline(self): - """Read line from remote.""" -- return self.file.readline() -+ line = self.file.readline(_MAXLINE + 1) -+ if len(line) > _MAXLINE: -+ raise self.error("got more than %d bytes" % _MAXLINE) -+ return line - - - def send(self, data): -diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py ---- a/Lib/test/test_imaplib.py -+++ b/Lib/test/test_imaplib.py -@@ -165,6 +165,16 @@ class BaseThreadedNetworkedTests(unittes - self.imap_class, *server.server_address) - - -+ def test_linetoolong(self): -+ class TooLongHandler(SimpleIMAPHandler): -+ def handle(self): -+ # Send a very long response line -+ self.wfile.write('* OK ' + imaplib._MAXLINE*'x' + '\r\n') -+ -+ with self.reaped_server(TooLongHandler) as server: -+ self.assertRaises(imaplib.IMAP4.error, -+ self.imap_class, *server.server_address) -+ - class ThreadedNetworkedTests(BaseThreadedNetworkedTests): - - server_class = SocketServer.TCPServer - -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() -diff --git a/Lib/poplib.py b/Lib/poplib.py ---- a/Lib/poplib.py -+++ b/Lib/poplib.py -@@ -32,6 +32,12 @@ CR = '\r' - LF = '\n' - CRLF = CR+LF - -+# maximal line length when calling readline(). This is to prevent -+# reading arbitrary length lines. RFC 1939 limits POP3 line length to -+# 512 characters, including CRLF. We have selected 2048 just to be on -+# the safe side. -+_MAXLINE = 2048 -+ - - class POP3: - -@@ -103,7 +109,9 @@ class POP3: - # Raise error_proto('-ERR EOF') if the connection is closed. - - def _getline(self): -- line = self.file.readline() -+ line = self.file.readline(_MAXLINE + 1) -+ if len(line) > _MAXLINE: -+ raise error_proto('line too long') - if self._debugging > 1: print '*get*', repr(line) - if not line: raise error_proto('-ERR EOF') - octets = len(line) -@@ -365,6 +373,8 @@ else: - match = renewline.match(self.buffer) - while not match: - self._fillBuffer() -+ if len(self.buffer) > _MAXLINE: -+ raise error_proto('line too long') - match = renewline.match(self.buffer) - line = match.group(0) - self.buffer = renewline.sub('' ,self.buffer, 1) -diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py ---- a/Lib/test/test_poplib.py -+++ b/Lib/test/test_poplib.py -@@ -198,6 +198,10 @@ class TestPOP3Class(TestCase): - 113) - self.assertEqual(self.client.retr('foo'), expected) - -+ def test_too_long_lines(self): -+ self.assertRaises(poplib.error_proto, self.client._shortcmd, -+ 'echo +%s' % ((poplib._MAXLINE + 10) * 'a')) -+ - def test_dele(self): - self.assertOK(self.client.dele('foo')) - -diff --git a/Lib/smtplib.py b/Lib/smtplib.py ---- a/Lib/smtplib.py -+++ b/Lib/smtplib.py -@@ -57,6 +57,7 @@ from sys import stderr - SMTP_PORT = 25 - SMTP_SSL_PORT = 465 - CRLF = "\r\n" -+_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3 - - OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) - -@@ -179,10 +180,14 @@ else: - def __init__(self, sslobj): - self.sslobj = sslobj - -- def readline(self): -+ def readline(self, size=-1): -+ if size < 0: -+ size = None - str = "" - chr = None - while chr != "\n": -+ if size is not None and len(str) >= size: -+ break - chr = self.sslobj.read(1) - if not chr: - break -@@ -353,7 +358,7 @@ class SMTP: - self.file = self.sock.makefile('rb') - while 1: - try: -- line = self.file.readline() -+ line = self.file.readline(_MAXLINE + 1) - except socket.error as e: - self.close() - raise SMTPServerDisconnected("Connection unexpectedly closed: " -@@ -363,6 +368,8 @@ class SMTP: - raise SMTPServerDisconnected("Connection unexpectedly closed") - if self.debuglevel > 0: - print>>stderr, 'reply:', repr(line) -+ if len(line) > _MAXLINE: -+ raise SMTPResponseException(500, "Line too long.") - resp.append(line[4:].strip()) - code = line[:3] - # Check that the error code is syntactically correct. -diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py ---- a/Lib/test/test_smtplib.py -+++ b/Lib/test/test_smtplib.py -@@ -292,6 +292,33 @@ class BadHELOServerTests(unittest.TestCa - HOST, self.port, 'localhost', 3) - - -+@unittest.skipUnless(threading, 'Threading required for this test.') -+class TooLongLineTests(unittest.TestCase): -+ respdata = '250 OK' + ('.' * smtplib._MAXLINE * 2) + '\n' -+ -+ def setUp(self): -+ self.old_stdout = sys.stdout -+ self.output = StringIO.StringIO() -+ sys.stdout = self.output -+ -+ self.evt = threading.Event() -+ self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -+ self.sock.settimeout(15) -+ self.port = test_support.bind_port(self.sock) -+ servargs = (self.evt, self.respdata, self.sock) -+ threading.Thread(target=server, args=servargs).start() -+ self.evt.wait() -+ self.evt.clear() -+ -+ def tearDown(self): -+ self.evt.wait() -+ sys.stdout = self.old_stdout -+ -+ def testLineTooLong(self): -+ self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP, -+ HOST, self.port, 'localhost', 3) -+ -+ - sim_users = {'Mr.A@somewhere.com':'John A', - 'Ms.B@somewhere.com':'Sally B', - 'Mrs.C@somewhereesle.com':'Ruth C', -@@ -526,7 +553,8 @@ class SMTPSimTests(unittest.TestCase): - def test_main(verbose=None): - test_support.run_unittest(GeneralTests, DebuggingServerTests, - NonConnectingTests, -- BadHELOServerTests, SMTPSimTests) -+ BadHELOServerTests, SMTPSimTests, -+ TooLongLineTests) - - if __name__ == '__main__': - test_main() -diff --git a/Lib/httplib.py b/Lib/httplib.py ---- a/Lib/httplib.py -+++ b/Lib/httplib.py -@@ -215,6 +215,10 @@ MAXAMOUNT = 1048576 - # maximal line length when calling readline(). - _MAXLINE = 65536 - -+# maximum amount of headers accepted -+_MAXHEADERS = 100 -+ -+ - class HTTPMessage(mimetools.Message): - - def addheader(self, key, value): -@@ -271,6 +275,8 @@ class HTTPMessage(mimetools.Message): - elif self.seekable: - tell = self.fp.tell - while True: -+ if len(hlist) > _MAXHEADERS: -+ raise HTTPException("got more than %d headers" % _MAXHEADERS) - if tell: - try: - startofline = tell() -diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py ---- a/Lib/test/test_httplib.py -+++ b/Lib/test/test_httplib.py -@@ -262,6 +262,13 @@ class BasicTest(TestCase): - if resp.read() != "": - self.fail("Did not expect response from HEAD request") - -+ def test_too_many_headers(self): -+ headers = '\r\n'.join('Header%d: foo' % i for i in xrange(200)) + '\r\n' -+ text = ('HTTP/1.1 200 OK\r\n' + headers) -+ s = FakeSocket(text) -+ r = httplib.HTTPResponse(s) -+ self.assertRaises(httplib.HTTPException, r.begin) -+ - def test_send_file(self): - expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \ - 'Accept-Encoding: identity\r\nContent-Length:' diff --git a/jython.spec b/jython.spec index e2050ec..a662885 100644 --- a/jython.spec +++ b/jython.spec @@ -1,7 +1,5 @@ -%{expand: %%global pyver %(python -c 'import sys;print(sys.version[0:3])')} - -%global cpython_version %{pyver} -%global scm_tag v2.7rc2 +%global cpython_version 2.7 +%global scm_tag v2.7rc3 # Turn off the brp-python-bytecompile script # We generate JVM bytecode instead @@ -9,7 +7,7 @@ Name: jython Version: 2.7 -Release: 0.7.rc2%{?dist} +Release: 0.8.rc3%{?dist} Summary: A Java implementation of the Python language License: ASL 1.1 and BSD and CNRI and JPython and Python URL: http://www.jython.org/ @@ -24,9 +22,6 @@ Patch0: jython-cachedir.patch # Avoid rebuilding and validating poms when installing maven stuff and don't gpg sign Patch1: jython-dont-validate-pom.patch -# Fix for CVE-2013-1752, see https://bugzilla.redhat.com/show_bug.cgi?id=1159201 -Patch2: jython-CVE-2013-1752.patch - Requires: python >= %{cpython_version} Requires: antlr32-java Requires: apache-commons-compress @@ -102,10 +97,6 @@ Demonstrations and samples for %{name}. %patch0 %patch1 -pushd lib-python/2.7 -%patch2 -p2 -popd - # Set correct encoding for source to fix javadoc generation sed -i -e '723i encoding="UTF-8"' build.xml @@ -203,6 +194,10 @@ EOF %{_datadir}/%{name}/Demo %changelog +* Tue Apr 21 2015 Mat Booth - 2.7-0.8.rc3 +- Update to release candidate 3 +- Drop upstreamed patch for CVE-2013-1752 + * Mon Apr 13 2015 Mat Booth - 2.7-0.7.rc2 - Fix CVE-2013-1752 - multiple unbound readline() DoS flaws in python stdlib diff --git a/sources b/sources index 913509b..2fcddda 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -0fb52f5e57b1bd274ed84e36da5a19d2 jython-v2.7rc2.tar.xz +6e73b2f3177270db7bba72bc29b617f9 jython-v2.7rc3.tar.xz