summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2020-09-05 12:23:00 +0100
committerColin Watson <cjwatson@debian.org>2020-09-05 12:23:43 +0100
commit5ba7958fcbbfaa5313291fe09bd9b3967d388a8a (patch)
treedeb7957b568552681f682cc7d9d470ab122d3fd0
parentc52ed1386b7d88d1dca5ce471bb8d23283c10837 (diff)
downloadzope-publisher-5ba7958fcbbfaa5313291fe09bd9b3967d388a8a.tar.gz
Fix handling of duplicate form-data field names
RFC 7578 section 5.2 says "Form parts with identical field names MUST NOT be coalesced". This was caught by the Launchpad test suite when testing an upgrade to zope.publisher 6.0.0.
-rw-r--r--src/zope/publisher/browser.py4
-rw-r--r--src/zope/publisher/tests/test_browserrequest.py21
2 files changed, 23 insertions, 2 deletions
diff --git a/src/zope/publisher/browser.py b/src/zope/publisher/browser.py
index 28d8666..b8f38ac 100644
--- a/src/zope/publisher/browser.py
+++ b/src/zope/publisher/browser.py
@@ -321,8 +321,8 @@ class BrowserRequest(HTTPRequest):
env['REQUEST_METHOD'] = 'POST'
forms, files = multipart.parse_form_data(
env, charset='ISO-8859-1', memfile_limit=0)
- items.extend(six.iteritems(forms))
- for key, item in six.iteritems(files):
+ items.extend(forms.iterallitems())
+ for key, item in files.iterallitems():
# multipart puts fields in 'files' even if no upload was
# made. We only consider fields to be file uploads if a
# filename was passed in and data was uploaded.
diff --git a/src/zope/publisher/tests/test_browserrequest.py b/src/zope/publisher/tests/test_browserrequest.py
index 1926bb3..dfcf7c6 100644
--- a/src/zope/publisher/tests/test_browserrequest.py
+++ b/src/zope/publisher/tests/test_browserrequest.py
@@ -601,6 +601,27 @@ class BrowserTests(HTTPTests):
publish(request)
self.assertEqual(request.form, {u"a": u"b +/=&b:int"})
+ def testFormMultipartDuplicateFieldNames(self):
+ extra = {
+ 'REQUEST_METHOD': 'POST',
+ 'CONTENT_TYPE': 'multipart/form_data; boundary=-123',
+ }
+ body = b'\n'.join([
+ b'---123',
+ b'Content-Disposition: form-data; name="a"',
+ b'',
+ b'first',
+ b'---123',
+ b'Content-Disposition: form-data; name="a"',
+ b'',
+ b'second',
+ b'---123--',
+ b'',
+ ])
+ request = self._createRequest(extra, body)
+ request.processInputs()
+ self.assertEqual(['first', 'second'], request.form['a'])
+
def testInterface(self):
request = self._createRequest()
verifyObject(IBrowserRequest, request)