Code

Ticket #15763: patch_limit_bytes_redundant.diff

File patch_limit_bytes_redundant.diff, 4.1 KB (added by tomchristie, 3 years ago)

Patch and test.

Line 
1Index: tests/regressiontests/file_uploads/tests.py
2===================================================================
3--- tests/regressiontests/file_uploads/tests.py (revision 16013)
4+++ tests/regressiontests/file_uploads/tests.py (working copy)
5@@ -151,6 +151,32 @@
6         got = simplejson.loads(self.client.request(**r).content)
7         self.assertTrue(len(got['file']) < 256, "Got a long file name (%s characters)." % len(got['file']))
8 
9+    def test_input_stream_is_limited(self):
10+        """
11+        If passed an incomplete multipart message, MultiPartParser does not
12+        attempt to read beyond the end of the stream.
13+        """
14+        payload = "\r\n".join([
15+            '--' + client.BOUNDARY,
16+            'Content-Disposition: form-data; name="file"; filename="foo.txt"',
17+            'Content-Type: application/octet-stream',
18+            '',
19+            'file contents'
20+            '--' + client.BOUNDARY + '--',
21+            '',
22+        ])
23+        payload = payload[:-10]
24+        r = {
25+            'CONTENT_LENGTH': len(payload),
26+            'CONTENT_TYPE':   client.MULTIPART_CONTENT,
27+            'PATH_INFO':      "/file_uploads/echo/",
28+            'REQUEST_METHOD': 'POST',
29+            'wsgi.input':     client.FakePayload(payload),
30+        }
31+        self.client.request(**r).content
32+        # FakePayload will have asserted a failure by now if MultiPartParser
33+        # attempted to read beyond the end of the payload.
34+
35     def test_custom_upload_handler(self):
36         # A small file (under the 5M quota)
37         smallfile = tempfile.NamedTemporaryFile()
38Index: django/http/multipartparser.py
39===================================================================
40--- django/http/multipartparser.py      (revision 16013)
41+++ django/http/multipartparser.py      (working copy)
42@@ -105,12 +105,10 @@
43         encoding = self._encoding
44         handlers = self._upload_handlers
45 
46-        limited_input_data = LimitBytes(self._input_data, self._content_length)
47-
48         # See if the handler will want to take care of the parsing.
49         # This allows overriding everything if somebody wants it.
50         for handler in handlers:
51-            result = handler.handle_raw_input(limited_input_data,
52+            result = handler.handle_raw_input(self._input_data,
53                                               self._meta,
54                                               self._content_length,
55                                               self._boundary,
56@@ -123,7 +121,7 @@
57         self._files = MultiValueDict()
58 
59         # Instantiate the parser and stream:
60-        stream = LazyStream(ChunkIter(limited_input_data, self._chunk_size))
61+        stream = LazyStream(ChunkIter(self._input_data, self._chunk_size))
62 
63         # Whether or not to signal a file-completion at the beginning of the loop.
64         old_field_name = None
65@@ -218,10 +216,10 @@
66                     exhaust(stream)
67         except StopUpload, e:
68             if not e.connection_reset:
69-                exhaust(limited_input_data)
70+                exhaust(self._input_data)
71         else:
72             # Make sure that the request data is all fed
73-            exhaust(limited_input_data)
74+            exhaust(self._input_data)
75 
76         # Signal that the upload has completed.
77         for handler in handlers:
78@@ -383,27 +381,6 @@
79     def __iter__(self):
80         return self
81 
82-class LimitBytes(object):
83-    """ Limit bytes for a file object. """
84-    def __init__(self, fileobject, length):
85-        self._file = fileobject
86-        self.remaining = length
87-
88-    def read(self, num_bytes=None):
89-        """
90-        Read data from the underlying file.
91-        If you ask for too much or there isn't anything left,
92-        this will raise an InputStreamExhausted error.
93-        """
94-        if self.remaining <= 0:
95-            raise InputStreamExhausted()
96-        if num_bytes is None:
97-            num_bytes = self.remaining
98-        else:
99-            num_bytes = min(num_bytes, self.remaining)
100-        self.remaining -= num_bytes
101-        return self._file.read(num_bytes)
102-
103 class InterBoundaryIter(object):
104     """
105     A Producer that will iterate over boundaries.