Solve SF bug #231249: cgi.py opens too many (temporary) files.
class FieldStorage: this patch changes read_lines() and co. to use a StringIO() instead of a real file. The write() calls are redirected to a private method that replaces it with a real, external file only when it gets too big (> 1000 bytes). This avoids problems in forms using the multipart/form-data encoding with many fields. The original code created a temporary file for *every* field (not just for file upload fields), thereby sometimes exceeding the open file limit of some systems. Note that the simpler solution "use a real file only for file uploads" can't be used because the form field parser has no way to tell which fields correspond to file uploads. It's *possible* but extremely unlikely that this would break someone's code; they would have to be stepping way outside the documented interface for FieldStorage and use f.file.fileno(), or depend on overriding make_file() to return a file-like object with additional known properties.
This commit is contained in:
parent
be4f0a7748
commit
52b8c29ca7
16
Lib/cgi.py
16
Lib/cgi.py
|
@ -28,7 +28,7 @@ written in Python.
|
|||
# responsible for its maintenance.
|
||||
#
|
||||
|
||||
__version__ = "2.5"
|
||||
__version__ = "2.6"
|
||||
|
||||
|
||||
# Imports
|
||||
|
@ -633,12 +633,20 @@ class FieldStorage:
|
|||
|
||||
def read_lines(self):
|
||||
"""Internal: read lines until EOF or outerboundary."""
|
||||
self.file = self.make_file('')
|
||||
self.file = self.__file = StringIO()
|
||||
if self.outerboundary:
|
||||
self.read_lines_to_outerboundary()
|
||||
else:
|
||||
self.read_lines_to_eof()
|
||||
|
||||
def __write(self, line):
|
||||
if self.__file is not None:
|
||||
if self.__file.tell() + len(line) > 1000:
|
||||
self.file = self.make_file('')
|
||||
self.file.write(self.__file.getvalue())
|
||||
self.__file = None
|
||||
self.file.write(line)
|
||||
|
||||
def read_lines_to_eof(self):
|
||||
"""Internal: read lines until EOF."""
|
||||
while 1:
|
||||
|
@ -646,7 +654,7 @@ class FieldStorage:
|
|||
if not line:
|
||||
self.done = -1
|
||||
break
|
||||
self.file.write(line)
|
||||
self.__write(line)
|
||||
|
||||
def read_lines_to_outerboundary(self):
|
||||
"""Internal: read lines until outerboundary."""
|
||||
|
@ -674,7 +682,7 @@ class FieldStorage:
|
|||
line = line[:-1]
|
||||
else:
|
||||
delim = ""
|
||||
self.file.write(odelim + line)
|
||||
self.__write(odelim + line)
|
||||
|
||||
def skip_lines(self):
|
||||
"""Internal: skip lines until outer boundary if defined."""
|
||||
|
|
Loading…
Reference in New Issue