This commit is contained in:
Benjamin Peterson 2014-12-05 20:34:56 -05:00
commit eca72d47f5
3 changed files with 37 additions and 4 deletions

View File

@ -863,7 +863,7 @@ class GzipServerTestCase(BaseServerTestCase):
p.pow(6, 8) p.pow(6, 8)
p("close")() p("close")()
def test_gsip_response(self): def test_gzip_response(self):
t = self.Transport() t = self.Transport()
p = xmlrpclib.ServerProxy(URL, transport=t) p = xmlrpclib.ServerProxy(URL, transport=t)
old = self.requestHandler.encode_threshold old = self.requestHandler.encode_threshold
@ -877,6 +877,27 @@ class GzipServerTestCase(BaseServerTestCase):
self.requestHandler.encode_threshold = old self.requestHandler.encode_threshold = old
self.assertTrue(a>b) self.assertTrue(a>b)
@unittest.skipIf(gzip is None, 'requires gzip')
class GzipUtilTestCase(unittest.TestCase):
def test_gzip_decode_limit(self):
max_gzip_decode = 20 * 1024 * 1024
data = b'\0' * max_gzip_decode
encoded = xmlrpclib.gzip_encode(data)
decoded = xmlrpclib.gzip_decode(encoded)
self.assertEqual(len(decoded), max_gzip_decode)
data = b'\0' * (max_gzip_decode + 1)
encoded = xmlrpclib.gzip_encode(data)
with self.assertRaisesRegexp(ValueError,
"max gzipped payload length exceeded"):
xmlrpclib.gzip_decode(encoded)
xmlrpclib.gzip_decode(encoded, max_decode=-1)
#Test special attributes of the ServerProxy object #Test special attributes of the ServerProxy object
class ServerProxyTestCase(unittest.TestCase): class ServerProxyTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
@ -1105,7 +1126,7 @@ def test_main():
support.run_unittest(XMLRPCTestCase, HelperTestCase, DateTimeTestCase, support.run_unittest(XMLRPCTestCase, HelperTestCase, DateTimeTestCase,
BinaryTestCase, FaultTestCase, UseBuiltinTypesTestCase, BinaryTestCase, FaultTestCase, UseBuiltinTypesTestCase,
SimpleServerTestCase, KeepaliveServerTestCase1, SimpleServerTestCase, KeepaliveServerTestCase1,
KeepaliveServerTestCase2, GzipServerTestCase, KeepaliveServerTestCase2, GzipServerTestCase, GzipUtilTestCase,
MultiPathServerTestCase, ServerProxyTestCase, FailingServerTestCase, MultiPathServerTestCase, ServerProxyTestCase, FailingServerTestCase,
CGIHandlerTestCase) CGIHandlerTestCase)

View File

@ -49,6 +49,7 @@
# 2003-07-12 gp Correct marshalling of Faults # 2003-07-12 gp Correct marshalling of Faults
# 2003-10-31 mvl Add multicall support # 2003-10-31 mvl Add multicall support
# 2004-08-20 mvl Bump minimum supported Python version to 2.1 # 2004-08-20 mvl Bump minimum supported Python version to 2.1
# 2014-12-02 ch/doko Add workaround for gzip bomb vulnerability
# #
# Copyright (c) 1999-2002 by Secret Labs AB. # Copyright (c) 1999-2002 by Secret Labs AB.
# Copyright (c) 1999-2002 by Fredrik Lundh. # Copyright (c) 1999-2002 by Fredrik Lundh.
@ -1030,10 +1031,13 @@ def gzip_encode(data):
# in the HTTP header, as described in RFC 1952 # in the HTTP header, as described in RFC 1952
# #
# @param data The encoded data # @param data The encoded data
# @keyparam max_decode Maximum bytes to decode (20MB default), use negative
# values for unlimited decoding
# @return the unencoded data # @return the unencoded data
# @raises ValueError if data is not correctly coded. # @raises ValueError if data is not correctly coded.
# @raises ValueError if max gzipped payload length exceeded
def gzip_decode(data): def gzip_decode(data, max_decode=20971520):
"""gzip encoded data -> unencoded data """gzip encoded data -> unencoded data
Decode data using the gzip content encoding as described in RFC 1952 Decode data using the gzip content encoding as described in RFC 1952
@ -1043,11 +1047,16 @@ def gzip_decode(data):
f = BytesIO(data) f = BytesIO(data)
gzf = gzip.GzipFile(mode="rb", fileobj=f) gzf = gzip.GzipFile(mode="rb", fileobj=f)
try: try:
decoded = gzf.read() if max_decode < 0: # no limit
decoded = gzf.read()
else:
decoded = gzf.read(max_decode + 1)
except OSError: except OSError:
raise ValueError("invalid data") raise ValueError("invalid data")
f.close() f.close()
gzf.close() gzf.close()
if max_decode >= 0 and len(decoded) > max_decode:
raise ValueError("max gzipped payload length exceeded")
return decoded return decoded
## ##

View File

@ -39,6 +39,9 @@ Core and Builtins
Library Library
------- -------
- Issue #16043: Add a default limit for the amount of data xmlrpclib.gzip_decode
will return. This resolves CVE-2013-1753.
- Issue #14099: ZipFile.open() no longer reopen the underlying file. Objects - Issue #14099: ZipFile.open() no longer reopen the underlying file. Objects
returned by ZipFile.open() can now operate independently of the ZipFile even returned by ZipFile.open() can now operate independently of the ZipFile even
if the ZipFile was created by passing in a file-like object as the first if the ZipFile was created by passing in a file-like object as the first