Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52b8c29

Browse files
committed
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.
1 parent be4f0a7 commit 52b8c29

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

Lib/cgi.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
# responsible for its maintenance.
2929
#
3030

31-
__version__ = "2.5"
31+
__version__ = "2.6"
3232

3333

3434
# Imports
@@ -633,20 +633,28 @@ def read_binary(self):
633633

634634
def read_lines(self):
635635
"""Internal: read lines until EOF or outerboundary."""
636-
self.file = self.make_file('')
636+
self.file = self.__file = StringIO()
637637
if self.outerboundary:
638638
self.read_lines_to_outerboundary()
639639
else:
640640
self.read_lines_to_eof()
641641

642+
def __write(self, line):
643+
if self.__file is not None:
644+
if self.__file.tell() + len(line) > 1000:
645+
self.file = self.make_file('')
646+
self.file.write(self.__file.getvalue())
647+
self.__file = None
648+
self.file.write(line)
649+
642650
def read_lines_to_eof(self):
643651
"""Internal: read lines until EOF."""
644652
while 1:
645653
line = self.fp.readline()
646654
if not line:
647655
self.done = -1
648656
break
649-
self.file.write(line)
657+
self.__write(line)
650658

651659
def read_lines_to_outerboundary(self):
652660
"""Internal: read lines until outerboundary."""
@@ -674,7 +682,7 @@ def read_lines_to_outerboundary(self):
674682
line = line[:-1]
675683
else:
676684
delim = ""
677-
self.file.write(odelim + line)
685+
self.__write(odelim + line)
678686

679687
def skip_lines(self):
680688
"""Internal: skip lines until outer boundary if defined."""

0 commit comments

Comments
 (0)