@@ -404,7 +404,8 @@ class FieldStorage:
404404 """
405405 def __init__ (self , fp = None , headers = None , outerboundary = b'' ,
406406 environ = os .environ , keep_blank_values = 0 , strict_parsing = 0 ,
407- limit = None , encoding = 'utf-8' , errors = 'replace' ):
407+ limit = None , encoding = 'utf-8' , errors = 'replace' ,
408+ max_num_fields = None ):
408409 """Constructor. Read multipart/* until last part.
409410
410411 Arguments, all optional:
@@ -444,10 +445,14 @@ def __init__(self, fp=None, headers=None, outerboundary=b'',
444445 for the page sending the form (content-type : meta http-equiv or
445446 header)
446447
448+ max_num_fields: int. If set, then __init__ throws a ValueError
449+ if there are more than n fields read by parse_qsl().
450+
447451 """
448452 method = 'GET'
449453 self .keep_blank_values = keep_blank_values
450454 self .strict_parsing = strict_parsing
455+ self .max_num_fields = max_num_fields
451456 if 'REQUEST_METHOD' in environ :
452457 method = environ ['REQUEST_METHOD' ].upper ()
453458 self .qs_on_post = None
@@ -670,12 +675,11 @@ def read_urlencoded(self):
670675 qs = qs .decode (self .encoding , self .errors )
671676 if self .qs_on_post :
672677 qs += '&' + self .qs_on_post
673- self .list = []
674678 query = urllib .parse .parse_qsl (
675679 qs , self .keep_blank_values , self .strict_parsing ,
676- encoding = self .encoding , errors = self .errors )
677- for key , value in query :
678- self .list . append ( MiniFieldStorage (key , value ))
680+ encoding = self .encoding , errors = self .errors ,
681+ max_num_fields = self . max_num_fields )
682+ self .list = [ MiniFieldStorage (key , value ) for key , value in query ]
679683 self .skip_lines ()
680684
681685 FieldStorageClass = None
@@ -689,9 +693,9 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
689693 if self .qs_on_post :
690694 query = urllib .parse .parse_qsl (
691695 self .qs_on_post , self .keep_blank_values , self .strict_parsing ,
692- encoding = self .encoding , errors = self .errors )
693- for key , value in query :
694- self .list .append (MiniFieldStorage (key , value ))
696+ encoding = self .encoding , errors = self .errors ,
697+ max_num_fields = self . max_num_fields )
698+ self .list .extend (MiniFieldStorage (key , value ) for key , value in query )
695699
696700 klass = self .FieldStorageClass or self .__class__
697701 first_line = self .fp .readline () # bytes
@@ -725,11 +729,23 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
725729 if 'content-length' in headers :
726730 del headers ['content-length' ]
727731
732+ # Propagate max_num_fields into the sub class appropriately
733+ sub_max_num_fields = self .max_num_fields
734+ if sub_max_num_fields is not None :
735+ sub_max_num_fields -= len (self .list )
736+
728737 part = klass (self .fp , headers , ib , environ , keep_blank_values ,
729738 strict_parsing ,self .limit - self .bytes_read ,
730- self .encoding , self .errors )
739+ self .encoding , self .errors , sub_max_num_fields )
740+
741+ max_num_fields = self .max_num_fields
742+ if max_num_fields is not None and part .list :
743+ max_num_fields -= len (part .list )
744+
731745 self .bytes_read += part .bytes_read
732746 self .list .append (part )
747+ if max_num_fields is not None and max_num_fields < len (self .list ):
748+ raise ValueError ('Max number of fields exceeded' )
733749 if part .done or self .bytes_read >= self .length > 0 :
734750 break
735751 self .skip_lines ()
0 commit comments