mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Issue #12411: Fix to cgi.parse_multipart to correctly use bytes boundaries and
bytes data. Patch by Jonas Wagner.
This commit is contained in:
parent
3d9e972270
commit
6b102f251f
3 changed files with 32 additions and 10 deletions
18
Lib/cgi.py
18
Lib/cgi.py
|
@ -214,17 +214,17 @@ def parse_multipart(fp, pdict):
|
||||||
"""
|
"""
|
||||||
import http.client
|
import http.client
|
||||||
|
|
||||||
boundary = ""
|
boundary = b""
|
||||||
if 'boundary' in pdict:
|
if 'boundary' in pdict:
|
||||||
boundary = pdict['boundary']
|
boundary = pdict['boundary']
|
||||||
if not valid_boundary(boundary):
|
if not valid_boundary(boundary):
|
||||||
raise ValueError('Invalid boundary in multipart form: %r'
|
raise ValueError('Invalid boundary in multipart form: %r'
|
||||||
% (boundary,))
|
% (boundary,))
|
||||||
|
|
||||||
nextpart = "--" + boundary
|
nextpart = b"--" + boundary
|
||||||
lastpart = "--" + boundary + "--"
|
lastpart = b"--" + boundary + b"--"
|
||||||
partdict = {}
|
partdict = {}
|
||||||
terminator = ""
|
terminator = b""
|
||||||
|
|
||||||
while terminator != lastpart:
|
while terminator != lastpart:
|
||||||
bytes = -1
|
bytes = -1
|
||||||
|
@ -243,7 +243,7 @@ def parse_multipart(fp, pdict):
|
||||||
raise ValueError('Maximum content length exceeded')
|
raise ValueError('Maximum content length exceeded')
|
||||||
data = fp.read(bytes)
|
data = fp.read(bytes)
|
||||||
else:
|
else:
|
||||||
data = ""
|
data = b""
|
||||||
# Read lines until end of part.
|
# Read lines until end of part.
|
||||||
lines = []
|
lines = []
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -251,7 +251,7 @@ def parse_multipart(fp, pdict):
|
||||||
if not line:
|
if not line:
|
||||||
terminator = lastpart # End outer loop
|
terminator = lastpart # End outer loop
|
||||||
break
|
break
|
||||||
if line.startswith("--"):
|
if line.startswith(b"--"):
|
||||||
terminator = line.rstrip()
|
terminator = line.rstrip()
|
||||||
if terminator in (nextpart, lastpart):
|
if terminator in (nextpart, lastpart):
|
||||||
break
|
break
|
||||||
|
@ -263,12 +263,12 @@ def parse_multipart(fp, pdict):
|
||||||
if lines:
|
if lines:
|
||||||
# Strip final line terminator
|
# Strip final line terminator
|
||||||
line = lines[-1]
|
line = lines[-1]
|
||||||
if line[-2:] == "\r\n":
|
if line[-2:] == b"\r\n":
|
||||||
line = line[:-2]
|
line = line[:-2]
|
||||||
elif line[-1:] == "\n":
|
elif line[-1:] == b"\n":
|
||||||
line = line[:-1]
|
line = line[:-1]
|
||||||
lines[-1] = line
|
lines[-1] = line
|
||||||
data = "".join(lines)
|
data = b"".join(lines)
|
||||||
line = headers['content-disposition']
|
line = headers['content-disposition']
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -4,6 +4,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
from collections import namedtuple
|
||||||
from io import StringIO, BytesIO
|
from io import StringIO, BytesIO
|
||||||
|
|
||||||
class HackedSysModule:
|
class HackedSysModule:
|
||||||
|
@ -118,6 +119,23 @@ def gen_result(data, environ):
|
||||||
|
|
||||||
class CgiTests(unittest.TestCase):
|
class CgiTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_parse_multipart(self):
|
||||||
|
fp = BytesIO(POSTDATA.encode('latin1'))
|
||||||
|
env = {'boundary': BOUNDARY.encode('latin1'),
|
||||||
|
'CONTENT-LENGTH': '558'}
|
||||||
|
result = cgi.parse_multipart(fp, env)
|
||||||
|
expected = {'submit': [b' Add '], 'id': [b'1234'],
|
||||||
|
'file': [b'Testing 123.\n'], 'title': [b'']}
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
def test_fieldstorage_properties(self):
|
||||||
|
fs = cgi.FieldStorage()
|
||||||
|
self.assertFalse(fs)
|
||||||
|
self.assertIn("FieldStorage", repr(fs))
|
||||||
|
self.assertEqual(list(fs), list(fs.keys()))
|
||||||
|
fs.list.append(namedtuple('MockFieldStorage', 'name')('fieldvalue'))
|
||||||
|
self.assertTrue(fs)
|
||||||
|
|
||||||
def test_escape(self):
|
def test_escape(self):
|
||||||
self.assertEqual("test & string", cgi.escape("test & string"))
|
self.assertEqual("test & string", cgi.escape("test & string"))
|
||||||
self.assertEqual("<test string>", cgi.escape("<test string>"))
|
self.assertEqual("<test string>", cgi.escape("<test string>"))
|
||||||
|
@ -151,7 +169,8 @@ class CgiTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_log(self):
|
def test_log(self):
|
||||||
cgi.log("Testing")
|
cgi.log("Testing")
|
||||||
|
cgi.logfile = "fail/"
|
||||||
|
cgi.initlog("%s", "Testing initlog")
|
||||||
cgi.logfp = StringIO()
|
cgi.logfp = StringIO()
|
||||||
cgi.initlog("%s", "Testing initlog 1")
|
cgi.initlog("%s", "Testing initlog 1")
|
||||||
cgi.log("%s", "Testing log 2")
|
cgi.log("%s", "Testing log 2")
|
||||||
|
|
|
@ -202,6 +202,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #12411: Fix to cgi.parse_multipart to correctly use bytes boundaries
|
||||||
|
and bytes data. Patch by Jonas Wagner.
|
||||||
|
|
||||||
- Issue #1159051: GzipFile now raises EOFError when reading a corrupted file
|
- Issue #1159051: GzipFile now raises EOFError when reading a corrupted file
|
||||||
with truncated header or footer.
|
with truncated header or footer.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue