]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Ignore any data after the final multipart boundary.
authorBen Darnell <ben@bendarnell.com>
Mon, 21 May 2012 06:03:53 +0000 (23:03 -0700)
committerBen Darnell <ben@bendarnell.com>
Mon, 21 May 2012 06:03:53 +0000 (23:03 -0700)
Closes #489.

tornado/httputil.py
tornado/test/httputil_test.py

index a1068224ee29e9a7045607483dca3ca15281155d..7d884e28bcba23018ad4c962199ef4643660c8a6 100644 (file)
@@ -215,11 +215,11 @@ def parse_multipart_form_data(boundary, data, arguments, files):
     # in the wild.
     if boundary.startswith(b('"')) and boundary.endswith(b('"')):
         boundary = boundary[1:-1]
-    if data.endswith(b("\r\n")):
-        footer_length = len(boundary) + 6
-    else:
-        footer_length = len(boundary) + 4
-    parts = data[:-footer_length].split(b("--") + boundary + b("\r\n"))
+    final_boundary_index = data.rfind(b("--") + boundary + b("--"))
+    if final_boundary_index == -1:
+        logging.warning("Invalid multipart/form-data: no final boundary")
+        return
+    parts = data[:final_boundary_index].split(b("--") + boundary + b("\r\n"))
     for part in parts:
         if not part:
             continue
index d0e58e9108dab5d0163f52bda41518a54eafdbee..736ed6d67a4dd154ac4cbf178b307c955ac1394a 100644 (file)
@@ -177,6 +177,24 @@ Foo
         parse_multipart_form_data(b("1234"), data, args, files)
         self.assertEqual(files, {})
 
+    def test_data_after_final_boundary(self):
+        # The spec requires that data after the final boundary be ignored.
+        # http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
+        # In practice, some libraries include an extra CRLF after the boundary.
+        data = b("""\
+--1234
+Content-Disposition: form-data; name="files"; filename="ab.txt"
+
+Foo
+--1234--
+""").replace(b("\n"), b("\r\n"))
+        args = {}
+        files = {}
+        parse_multipart_form_data(b("1234"), data, args, files)
+        file = files["files"][0]
+        self.assertEqual(file["filename"], "ab.txt")
+        self.assertEqual(file["body"], b("Foo"))
+
 
 class HTTPHeadersTest(unittest.TestCase):
     def test_multi_line(self):