An interpreted, interactive, object-oriented programming language
CentOS Sources
2017-08-01 71084d584ff953f5463757ec6536406320560b4d
commit | author | age
f63228 1
CS 2 # HG changeset patch
3 # User Benjamin Peterson <benjamin@python.org>
4 # Date 1417828515 18000
5 # Node ID d50096708b2d701937e78f525446d729fc28db88
6 # Parent  923aac88a3cc76a95d5a04d9d3ece245147a8064
7 add a default limit for the amount of data xmlrpclib.gzip_decode will return (closes #16043)
8
9 diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
10 --- a/Lib/test/test_xmlrpc.py
11 +++ b/Lib/test/test_xmlrpc.py
12 @@ -737,7 +737,7 @@ class GzipServerTestCase(BaseServerTestC
13          with cm:
14              p.pow(6, 8)
15  
16 -    def test_gsip_response(self):
17 +    def test_gzip_response(self):
18          t = self.Transport()
19          p = xmlrpclib.ServerProxy(URL, transport=t)
20          old = self.requestHandler.encode_threshold
21 @@ -750,6 +750,23 @@ class GzipServerTestCase(BaseServerTestC
22          self.requestHandler.encode_threshold = old
23          self.assertTrue(a>b)
24  
25 +    def test_gzip_decode_limit(self):
26 +        max_gzip_decode = 20 * 1024 * 1024
27 +        data = '\0' * max_gzip_decode
28 +        encoded = xmlrpclib.gzip_encode(data)
29 +        decoded = xmlrpclib.gzip_decode(encoded)
30 +        self.assertEqual(len(decoded), max_gzip_decode)
31 +
32 +        data = '\0' * (max_gzip_decode + 1)
33 +        encoded = xmlrpclib.gzip_encode(data)
34 +
35 +        with self.assertRaisesRegexp(ValueError,
36 +                                     "max gzipped payload length exceeded"):
37 +            xmlrpclib.gzip_decode(encoded)
38 +
39 +        xmlrpclib.gzip_decode(encoded, max_decode=-1)
40 +
41 +
42  #Test special attributes of the ServerProxy object
43  class ServerProxyTestCase(unittest.TestCase):
44      def setUp(self):
45 diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py
46 --- a/Lib/xmlrpclib.py
47 +++ b/Lib/xmlrpclib.py
48 @@ -49,6 +49,7 @@
49  # 2003-07-12 gp  Correct marshalling of Faults
50  # 2003-10-31 mvl Add multicall support
51  # 2004-08-20 mvl Bump minimum supported Python version to 2.1
52 +# 2014-12-02 ch/doko  Add workaround for gzip bomb vulnerability
53  #
54  # Copyright (c) 1999-2002 by Secret Labs AB.
55  # Copyright (c) 1999-2002 by Fredrik Lundh.
56 @@ -1165,10 +1166,13 @@ def gzip_encode(data):
57  # in the HTTP header, as described in RFC 1952
58  #
59  # @param data The encoded data
60 +# @keyparam max_decode Maximum bytes to decode (20MB default), use negative
61 +#    values for unlimited decoding
62  # @return the unencoded data
63  # @raises ValueError if data is not correctly coded.
64 +# @raises ValueError if max gzipped payload length exceeded
65  
66 -def gzip_decode(data):
67 +def gzip_decode(data, max_decode=20971520):
68      """gzip encoded data -> unencoded data
69  
70      Decode data using the gzip content encoding as described in RFC 1952
71 @@ -1178,11 +1182,16 @@ def gzip_decode(data):
72      f = StringIO.StringIO(data)
73      gzf = gzip.GzipFile(mode="rb", fileobj=f)
74      try:
75 -        decoded = gzf.read()
76 +        if max_decode < 0: # no limit
77 +            decoded = gzf.read()
78 +        else:
79 +            decoded = gzf.read(max_decode + 1)
80      except IOError:
81          raise ValueError("invalid data")
82      f.close()
83      gzf.close()
84 +    if max_decode >= 0 and len(decoded) > max_decode:
85 +        raise ValueError("max gzipped payload length exceeded")
86      return decoded
87  
88  ##