summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Hobbs <jason.hobbs@gmail.com>2014-09-02 12:23:51 -0500
committerClaude Paroz <claude@2xlibre.net>2014-09-13 19:06:21 +0200
commite1424b237003723c12400b5e1cfd95c87650e62b (patch)
tree3c8b567859101f7a3d08b795db2c1dbcf244c9de
parent22bfc451467ec6e13044a87a97cf00e9f8a845e4 (diff)
Fixed #23397 -- Stripped whitespace from base64 during chunking
This insures the actual base64 content has a length a multiple of 4. Also added a test case for the failure.
-rw-r--r--django/http/multipartparser.py17
-rw-r--r--tests/file_uploads/tests.py8
2 files changed, 17 insertions, 8 deletions
diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py
index fd9f3a5b32..07c874e08f 100644
--- a/django/http/multipartparser.py
+++ b/django/http/multipartparser.py
@@ -206,14 +206,19 @@ class MultiPartParser(object):
for chunk in field_stream:
if transfer_encoding == 'base64':
# We only special-case base64 transfer encoding
- # We should always read base64 streams by multiple of 4
- over_bytes = len(chunk) % 4
- if over_bytes:
- over_chunk = field_stream.read(4 - over_bytes)
- chunk += over_chunk
+ # We should always decode base64 chunks by multiple of 4,
+ # ignoring whitespace.
+
+ stripped_chunk = b"".join(chunk.split())
+
+ remaining = len(stripped_chunk) % 4
+ while remaining != 0:
+ over_chunk = field_stream.read(4 - remaining)
+ stripped_chunk += b"".join(over_chunk.split())
+ remaining = len(stripped_chunk) % 4
try:
- chunk = base64.b64decode(chunk)
+ chunk = base64.b64decode(stripped_chunk)
except Exception as e:
# Since this is only a chunk, any error is an unfixable error.
msg = "Could not decode base64 data: %r" % e
diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py
index 39f4caf6cd..66d055e8cf 100644
--- a/tests/file_uploads/tests.py
+++ b/tests/file_uploads/tests.py
@@ -77,14 +77,14 @@ class FileUploadTests(TestCase):
self.assertEqual(response.status_code, 200)
- def _test_base64_upload(self, content):
+ def _test_base64_upload(self, content, encode=base64.b64encode):
payload = client.FakePayload("\r\n".join([
'--' + client.BOUNDARY,
'Content-Disposition: form-data; name="file"; filename="test.txt"',
'Content-Type: application/octet-stream',
'Content-Transfer-Encoding: base64',
'']))
- payload.write(b"\r\n" + base64.b64encode(force_bytes(content)) + b"\r\n")
+ payload.write(b"\r\n" + encode(force_bytes(content)) + b"\r\n")
payload.write('--' + client.BOUNDARY + '--\r\n')
r = {
'CONTENT_LENGTH': len(payload),
@@ -104,6 +104,10 @@ class FileUploadTests(TestCase):
def test_big_base64_upload(self):
self._test_base64_upload("Big data" * 68000) # > 512Kb
+ def test_big_base64_newlines_upload(self):
+ self._test_base64_upload(
+ "Big data" * 68000, encode=base64.encodestring)
+
def test_unicode_file_name(self):
tdir = sys_tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, tdir, True)