Kaydet (Commit) 5c23b8e6 authored tarafından Victor Stinner's avatar Victor Stinner

Issue #4953: cgi.FieldStorage and cgi.parse() parse the request as bytes, not

as unicode, and accept binary files. Add encoding and errors attributes to
cgi.FieldStorage.
üst 1d87deb6
This diff is collapsed.
...@@ -4,7 +4,7 @@ import os ...@@ -4,7 +4,7 @@ import os
import sys import sys
import tempfile import tempfile
import unittest import unittest
from io import StringIO from io import StringIO, BytesIO
class HackedSysModule: class HackedSysModule:
# The regression test will have real values in sys.argv, which # The regression test will have real values in sys.argv, which
...@@ -14,7 +14,6 @@ class HackedSysModule: ...@@ -14,7 +14,6 @@ class HackedSysModule:
cgi.sys = HackedSysModule() cgi.sys = HackedSysModule()
class ComparableException: class ComparableException:
def __init__(self, err): def __init__(self, err):
self.err = err self.err = err
...@@ -38,7 +37,7 @@ def do_test(buf, method): ...@@ -38,7 +37,7 @@ def do_test(buf, method):
env['REQUEST_METHOD'] = 'GET' env['REQUEST_METHOD'] = 'GET'
env['QUERY_STRING'] = buf env['QUERY_STRING'] = buf
elif method == "POST": elif method == "POST":
fp = StringIO(buf) fp = BytesIO(buf.encode('latin-1')) # FieldStorage expects bytes
env['REQUEST_METHOD'] = 'POST' env['REQUEST_METHOD'] = 'POST'
env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
env['CONTENT_LENGTH'] = str(len(buf)) env['CONTENT_LENGTH'] = str(len(buf))
...@@ -106,9 +105,10 @@ def first_second_elts(list): ...@@ -106,9 +105,10 @@ def first_second_elts(list):
return [(p[0], p[1][0]) for p in list] return [(p[0], p[1][0]) for p in list]
def gen_result(data, environ): def gen_result(data, environ):
fake_stdin = StringIO(data) encoding = 'latin-1'
fake_stdin = BytesIO(data.encode(encoding))
fake_stdin.seek(0) fake_stdin.seek(0)
form = cgi.FieldStorage(fp=fake_stdin, environ=environ) form = cgi.FieldStorage(fp=fake_stdin, environ=environ, encoding=encoding)
result = {} result = {}
for k, v in dict(form).items(): for k, v in dict(form).items():
...@@ -122,9 +122,9 @@ class CgiTests(unittest.TestCase): ...@@ -122,9 +122,9 @@ class CgiTests(unittest.TestCase):
for orig, expect in parse_strict_test_cases: for orig, expect in parse_strict_test_cases:
# Test basic parsing # Test basic parsing
d = do_test(orig, "GET") d = do_test(orig, "GET")
self.assertEqual(d, expect, "Error parsing %s" % repr(orig)) self.assertEqual(d, expect, "Error parsing %s method GET" % repr(orig))
d = do_test(orig, "POST") d = do_test(orig, "POST")
self.assertEqual(d, expect, "Error parsing %s" % repr(orig)) self.assertEqual(d, expect, "Error parsing %s method POST" % repr(orig))
env = {'QUERY_STRING': orig} env = {'QUERY_STRING': orig}
fs = cgi.FieldStorage(environ=env) fs = cgi.FieldStorage(environ=env)
...@@ -181,9 +181,9 @@ class CgiTests(unittest.TestCase): ...@@ -181,9 +181,9 @@ class CgiTests(unittest.TestCase):
setattr(self, name, a) setattr(self, name, a)
return a return a
f = TestReadlineFile(tempfile.TemporaryFile("w+")) f = TestReadlineFile(tempfile.TemporaryFile("wb+"))
self.addCleanup(f.close) self.addCleanup(f.close)
f.write('x' * 256 * 1024) f.write(b'x' * 256 * 1024)
f.seek(0) f.seek(0)
env = {'REQUEST_METHOD':'PUT'} env = {'REQUEST_METHOD':'PUT'}
fs = cgi.FieldStorage(fp=f, environ=env) fs = cgi.FieldStorage(fp=f, environ=env)
...@@ -192,6 +192,7 @@ class CgiTests(unittest.TestCase): ...@@ -192,6 +192,7 @@ class CgiTests(unittest.TestCase):
# (by read_binary); if we are chunking properly, it will be called 5 times # (by read_binary); if we are chunking properly, it will be called 5 times
# as long as the chunksize is 1 << 16. # as long as the chunksize is 1 << 16.
self.assertTrue(f.numcalls > 2) self.assertTrue(f.numcalls > 2)
f.close()
def test_fieldstorage_multipart(self): def test_fieldstorage_multipart(self):
#Test basic FieldStorage multipart parsing #Test basic FieldStorage multipart parsing
...@@ -216,11 +217,13 @@ Content-Disposition: form-data; name="submit" ...@@ -216,11 +217,13 @@ Content-Disposition: form-data; name="submit"
Add\x20 Add\x20
-----------------------------721837373350705526688164684-- -----------------------------721837373350705526688164684--
""" """
fs = cgi.FieldStorage(fp=StringIO(postdata), environ=env) encoding = 'ascii'
fp = BytesIO(postdata.encode(encoding))
fs = cgi.FieldStorage(fp, environ=env, encoding=encoding)
self.assertEqual(len(fs.list), 4) self.assertEqual(len(fs.list), 4)
expect = [{'name':'id', 'filename':None, 'value':'1234'}, expect = [{'name':'id', 'filename':None, 'value':'1234'},
{'name':'title', 'filename':None, 'value':''}, {'name':'title', 'filename':None, 'value':''},
{'name':'file', 'filename':'test.txt', 'value':'Testing 123.'}, {'name':'file', 'filename':'test.txt', 'value':b'Testing 123.\n'},
{'name':'submit', 'filename':None, 'value':' Add '}] {'name':'submit', 'filename':None, 'value':' Add '}]
for x in range(len(fs.list)): for x in range(len(fs.list)):
for k, exp in expect[x].items(): for k, exp in expect[x].items():
...@@ -245,8 +248,7 @@ Content-Disposition: form-data; name="submit" ...@@ -245,8 +248,7 @@ Content-Disposition: form-data; name="submit"
self.assertEqual(self._qs_result, v) self.assertEqual(self._qs_result, v)
def testQSAndFormData(self): def testQSAndFormData(self):
data = """ data = """---123
---123
Content-Disposition: form-data; name="key2" Content-Disposition: form-data; name="key2"
value2y value2y
...@@ -270,8 +272,7 @@ value4 ...@@ -270,8 +272,7 @@ value4
self.assertEqual(self._qs_result, v) self.assertEqual(self._qs_result, v)
def testQSAndFormDataFile(self): def testQSAndFormDataFile(self):
data = """ data = """---123
---123
Content-Disposition: form-data; name="key2" Content-Disposition: form-data; name="key2"
value2y value2y
...@@ -299,7 +300,7 @@ this is the content of the fake file ...@@ -299,7 +300,7 @@ this is the content of the fake file
} }
result = self._qs_result.copy() result = self._qs_result.copy()
result.update({ result.update({
'upload': 'this is the content of the fake file' 'upload': b'this is the content of the fake file\n'
}) })
v = gen_result(data, environ) v = gen_result(data, environ)
self.assertEqual(result, v) self.assertEqual(result, v)
......
...@@ -43,6 +43,10 @@ Core and Builtins ...@@ -43,6 +43,10 @@ Core and Builtins
Library Library
------- -------
- Issue #4953: cgi.FieldStorage and cgi.parse() parse the request as bytes, not
as unicode, and accept binary files. Add encoding and errors attributes to
cgi.FieldStorage.
- Add encoding and errors arguments to urllib.parse_qs() and urllib.parse_qsl() - Add encoding and errors arguments to urllib.parse_qs() and urllib.parse_qsl()
- Issue #10899: No function type annotations in the standard library. - Issue #10899: No function type annotations in the standard library.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment