Skip to content

Commit e8f968d

Browse files
miss-islingtonhawkowl
authored andcommitted
bpo-33497: Add errors param to cgi.parse_multipart and make an encoding in FieldStorage use the given errors (GH-6804) (GH-6837)
(cherry picked from commit 545c955) Co-authored-by: Amber Brown <[email protected]>
1 parent 8e633a4 commit e8f968d

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed

Doc/library/cgi.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ algorithms implemented in this module in other circumstances.
296296
instead. It is maintained here only for backward compatibility.
297297

298298

299-
.. function:: parse_multipart(fp, pdict, encoding="utf-8")
299+
.. function:: parse_multipart(fp, pdict, encoding="utf-8", errors="replace")
300300

301301
Parse input of type :mimetype:`multipart/form-data` (for file uploads).
302302
Arguments are *fp* for the input file, *pdict* for a dictionary containing
@@ -312,8 +312,8 @@ algorithms implemented in this module in other circumstances.
312312
which is much more flexible.
313313

314314
.. versionchanged:: 3.7
315-
Added the *encoding* parameter. For non-file fields, the value is now
316-
a list of strings, not bytes.
315+
Added the *encoding* and *errors* parameters. For non-file fields, the
316+
value is now a list of strings, not bytes.
317317

318318

319319
.. function:: parse_header(string)

Lib/cgi.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,14 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
198198
DeprecationWarning, 2)
199199
return urllib.parse.parse_qsl(qs, keep_blank_values, strict_parsing)
200200

201-
def parse_multipart(fp, pdict, encoding="utf-8"):
201+
def parse_multipart(fp, pdict, encoding="utf-8", errors="replace"):
202202
"""Parse multipart input.
203203
204204
Arguments:
205205
fp : input file
206206
pdict: dictionary containing other parameters of content-type header
207-
encoding: request encoding
207+
encoding, errors: request encoding and error handler, passed to
208+
FieldStorage
208209
209210
Returns a dictionary just like parse_qs(): keys are the field names, each
210211
value is a list of values for that field. For non-file fields, the value
@@ -217,7 +218,7 @@ def parse_multipart(fp, pdict, encoding="utf-8"):
217218
headers = Message()
218219
headers.set_type(ctype)
219220
headers['Content-Length'] = pdict['CONTENT-LENGTH']
220-
fs = FieldStorage(fp, headers=headers, encoding=encoding,
221+
fs = FieldStorage(fp, headers=headers, encoding=encoding, errors=errors,
221222
environ={'REQUEST_METHOD': 'POST'})
222223
return {k: fs.getlist(k) for k in fs}
223224

@@ -458,7 +459,8 @@ def __init__(self, fp=None, headers=None, outerboundary=b'',
458459
self.type = ctype
459460
self.type_options = pdict
460461
if 'boundary' in pdict:
461-
self.innerboundary = pdict['boundary'].encode(self.encoding)
462+
self.innerboundary = pdict['boundary'].encode(self.encoding,
463+
self.errors)
462464
else:
463465
self.innerboundary = b""
464466

Lib/test/test_cgi.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,24 @@ def test_parse_multipart(self):
130130
'file': [b'Testing 123.\n'], 'title': ['']}
131131
self.assertEqual(result, expected)
132132

133+
def test_parse_multipart_invalid_encoding(self):
134+
BOUNDARY = "JfISa01"
135+
POSTDATA = """--JfISa01
136+
Content-Disposition: form-data; name="submit-name"
137+
Content-Length: 3
138+
139+
\u2603
140+
--JfISa01"""
141+
fp = BytesIO(POSTDATA.encode('utf8'))
142+
env = {'boundary': BOUNDARY.encode('latin1'),
143+
'CONTENT-LENGTH': str(len(POSTDATA.encode('utf8')))}
144+
result = cgi.parse_multipart(fp, env, encoding="ascii",
145+
errors="surrogateescape")
146+
expected = {'submit-name': ["\udce2\udc98\udc83"]}
147+
self.assertEqual(result, expected)
148+
self.assertEqual("\u2603".encode('utf8'),
149+
result["submit-name"][0].encode('utf8', 'surrogateescape'))
150+
133151
def test_fieldstorage_properties(self):
134152
fs = cgi.FieldStorage()
135153
self.assertFalse(fs)

0 commit comments

Comments
 (0)