Fixes issue 27777: cgi.FieldStorage can't parse simple body with Content-Length and no Content-Disposition
- If content length is present, read at most len bytes. - When reading `read_lines_to_eof` use `read` instead of `readline`. - Use `self.__write` even when content length is present and > 1000.
This commit is contained in:
parent
b0689ae7f9
commit
8e491e7ba5
31
Lib/cgi.py
31
Lib/cgi.py
|
@ -667,7 +667,7 @@ class FieldStorage:
|
|||
def read_single(self):
|
||||
"""Internal: read an atomic part."""
|
||||
if self.length >= 0:
|
||||
self.read_binary()
|
||||
self.read_content()
|
||||
self.skip_lines()
|
||||
else:
|
||||
self.read_lines()
|
||||
|
@ -675,31 +675,30 @@ class FieldStorage:
|
|||
|
||||
bufsize = 8*1024 # I/O buffering size for copy to file
|
||||
|
||||
def read_binary(self):
|
||||
"""Internal: read binary data."""
|
||||
self.file = self.make_file()
|
||||
def read_content(self):
|
||||
"""Internal: read data up until content-length len."""
|
||||
if self.length > 1000:
|
||||
self.file = self.make_file()
|
||||
else:
|
||||
self.file = self.io_object()
|
||||
todo = self.length
|
||||
if todo >= 0:
|
||||
while todo > 0:
|
||||
data = self.fp.read(min(todo, self.bufsize)) # bytes
|
||||
if not isinstance(data, bytes):
|
||||
raise ValueError("%s should return bytes, got %s"
|
||||
% (self.fp, type(data).__name__))
|
||||
self.bytes_read += len(data)
|
||||
if not data:
|
||||
self.done = -1
|
||||
break
|
||||
self.file.write(data)
|
||||
self.__write(data)
|
||||
todo = todo - len(data)
|
||||
|
||||
def read_lines(self):
|
||||
"""Internal: read lines until EOF or outerboundary."""
|
||||
if self._binary_file:
|
||||
self.file = self.__file = BytesIO() # store data as bytes for files
|
||||
else:
|
||||
self.file = self.__file = StringIO() # as strings for other fields
|
||||
self.file = self.__file = self.io_object()
|
||||
if self.outerboundary:
|
||||
self.read_lines_to_outerboundary()
|
||||
elif self.length >= 0:
|
||||
self.read_content()
|
||||
else:
|
||||
self.read_lines_to_eof()
|
||||
|
||||
|
@ -721,7 +720,7 @@ class FieldStorage:
|
|||
def read_lines_to_eof(self):
|
||||
"""Internal: read lines until EOF."""
|
||||
while 1:
|
||||
line = self.fp.readline(1<<16) # bytes
|
||||
line = self.fp.read(1<<16) # bytes
|
||||
self.bytes_read += len(line)
|
||||
if not line:
|
||||
self.done = -1
|
||||
|
@ -830,6 +829,12 @@ class FieldStorage:
|
|||
return tempfile.TemporaryFile("w+",
|
||||
encoding=self.encoding, newline = '\n')
|
||||
|
||||
def io_object(self):
|
||||
if self._binary_file:
|
||||
return BytesIO() # store data as bytes for files
|
||||
else:
|
||||
return StringIO() # as strings for other fields
|
||||
|
||||
|
||||
# Test/debug code
|
||||
# ===============
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fixes a bug in :mod:`cgi` when a request has a "Content-Length" header but
|
||||
without "Content-Disposition" headers.
|
Loading…
Reference in New Issue