comparison Lib/cgi.py @ 21211:151b6967bd21 2.1

backport of 1.64, 1.65, 1.68: 1.64: Solve SF bug #231249: cgi.py opens too many (temporary) files. 1.65: Fix a denial-of-service attack, SF bug #443120. 1.68: "ib" should be "boundary"; reported by Neal Norwitz. the first two of these are pretty severe bugs.
author Anthony Baxter <anthonybaxter@gmail.com>
date Wed, 05 Dec 2001 05:10:28 +0000
parents 8323b098c6ce
children
comparison
equal deleted inserted replaced
21210:2d21650f46f8 21211:151b6967bd21
26 # parsing was inspired by code submitted by Andreas Paepcke. Guido van 26 # parsing was inspired by code submitted by Andreas Paepcke. Guido van
27 # Rossum rewrote, reformatted and documented the module and is currently 27 # Rossum rewrote, reformatted and documented the module and is currently
28 # responsible for its maintenance. 28 # responsible for its maintenance.
29 # 29 #
30 30
31 __version__ = "2.5" 31 __version__ = "2.6"
32 32
33 33
34 # Imports 34 # Imports
35 # ======= 35 # =======
36 36
241 241
242 XXX This should really be subsumed by FieldStorage altogether -- no 242 XXX This should really be subsumed by FieldStorage altogether -- no
243 point in having two implementations of the same parsing algorithm. 243 point in having two implementations of the same parsing algorithm.
244 244
245 """ 245 """
246 boundary = ""
246 if pdict.has_key('boundary'): 247 if pdict.has_key('boundary'):
247 boundary = pdict['boundary'] 248 boundary = pdict['boundary']
248 else: 249 if not valid_boundary(boundary):
249 boundary = "" 250 raise ValueError, ('Invalid boundary in multipart form: %s'
251 % `boundary`)
252
250 nextpart = "--" + boundary 253 nextpart = "--" + boundary
251 lastpart = "--" + boundary + "--" 254 lastpart = "--" + boundary + "--"
252 partdict = {} 255 partdict = {}
253 terminator = "" 256 terminator = ""
254 257
593 596
594 FieldStorageClass = None 597 FieldStorageClass = None
595 598
596 def read_multi(self, environ, keep_blank_values, strict_parsing): 599 def read_multi(self, environ, keep_blank_values, strict_parsing):
597 """Internal: read a part that is itself multipart.""" 600 """Internal: read a part that is itself multipart."""
601 ib = self.innerboundary
602 if not valid_boundary(ib):
603 raise ValueError, ('Invalid boundary in multipart form: %s'
604 % `ib`)
598 self.list = [] 605 self.list = []
599 klass = self.FieldStorageClass or self.__class__ 606 klass = self.FieldStorageClass or self.__class__
600 part = klass(self.fp, {}, self.innerboundary, 607 part = klass(self.fp, {}, ib,
601 environ, keep_blank_values, strict_parsing) 608 environ, keep_blank_values, strict_parsing)
602 # Throw first part away 609 # Throw first part away
603 while not part.done: 610 while not part.done:
604 headers = rfc822.Message(self.fp) 611 headers = rfc822.Message(self.fp)
605 part = klass(self.fp, headers, self.innerboundary, 612 part = klass(self.fp, headers, ib,
606 environ, keep_blank_values, strict_parsing) 613 environ, keep_blank_values, strict_parsing)
607 self.list.append(part) 614 self.list.append(part)
608 self.skip_lines() 615 self.skip_lines()
609 616
610 def read_single(self): 617 def read_single(self):
631 self.file.write(data) 638 self.file.write(data)
632 todo = todo - len(data) 639 todo = todo - len(data)
633 640
634 def read_lines(self): 641 def read_lines(self):
635 """Internal: read lines until EOF or outerboundary.""" 642 """Internal: read lines until EOF or outerboundary."""
636 self.file = self.make_file('') 643 self.file = self.__file = StringIO()
637 if self.outerboundary: 644 if self.outerboundary:
638 self.read_lines_to_outerboundary() 645 self.read_lines_to_outerboundary()
639 else: 646 else:
640 self.read_lines_to_eof() 647 self.read_lines_to_eof()
648
649 def __write(self, line):
650 if self.__file is not None:
651 if self.__file.tell() + len(line) > 1000:
652 self.file = self.make_file('')
653 self.file.write(self.__file.getvalue())
654 self.__file = None
655 self.file.write(line)
641 656
642 def read_lines_to_eof(self): 657 def read_lines_to_eof(self):
643 """Internal: read lines until EOF.""" 658 """Internal: read lines until EOF."""
644 while 1: 659 while 1:
645 line = self.fp.readline() 660 line = self.fp.readline()
646 if not line: 661 if not line:
647 self.done = -1 662 self.done = -1
648 break 663 break
649 self.file.write(line) 664 self.__write(line)
650 665
651 def read_lines_to_outerboundary(self): 666 def read_lines_to_outerboundary(self):
652 """Internal: read lines until outerboundary.""" 667 """Internal: read lines until outerboundary."""
653 next = "--" + self.outerboundary 668 next = "--" + self.outerboundary
654 last = next + "--" 669 last = next + "--"
672 elif line[-1] == "\n": 687 elif line[-1] == "\n":
673 delim = "\n" 688 delim = "\n"
674 line = line[:-1] 689 line = line[:-1]
675 else: 690 else:
676 delim = "" 691 delim = ""
677 self.file.write(odelim + line) 692 self.__write(odelim + line)
678 693
679 def skip_lines(self): 694 def skip_lines(self):
680 """Internal: skip lines until outer boundary if defined.""" 695 """Internal: skip lines until outer boundary if defined."""
681 if not self.outerboundary or self.done: 696 if not self.outerboundary or self.done:
682 return 697 return
989 s = s.replace(">", "&gt;") 1004 s = s.replace(">", "&gt;")
990 if quote: 1005 if quote:
991 s = s.replace('"', "&quot;") 1006 s = s.replace('"', "&quot;")
992 return s 1007 return s
993 1008
1009 def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1010 import re
1011 return re.match(_vb_pattern, s)
994 1012
995 # Invoke mainline 1013 # Invoke mainline
996 # =============== 1014 # ===============
997 1015
998 # Call test() when this file is run as a script (not imported as a module) 1016 # Call test() when this file is run as a script (not imported as a module)