@@ -328,7 +328,8 @@ class FieldStorage:
328328 """
329329 def __init__ (self , fp = None , headers = None , outerboundary = b'' ,
330330 environ = os .environ , keep_blank_values = 0 , strict_parsing = 0 ,
331- limit = None , encoding = 'utf-8' , errors = 'replace' ):
331+ limit = None , encoding = 'utf-8' , errors = 'replace' ,
332+ max_num_fields = None ):
332333 """Constructor. Read multipart/* until last part.
333334
334335 Arguments, all optional:
@@ -368,10 +369,14 @@ def __init__(self, fp=None, headers=None, outerboundary=b'',
368369 for the page sending the form (content-type : meta http-equiv or
369370 header)
370371
372+ max_num_fields: int. If set, then __init__ throws a ValueError
373+ if there are more than n fields read by parse_qsl().
374+
371375 """
372376 method = 'GET'
373377 self .keep_blank_values = keep_blank_values
374378 self .strict_parsing = strict_parsing
379+ self .max_num_fields = max_num_fields
375380 if 'REQUEST_METHOD' in environ :
376381 method = environ ['REQUEST_METHOD' ].upper ()
377382 self .qs_on_post = None
@@ -595,12 +600,11 @@ def read_urlencoded(self):
595600 qs = qs .decode (self .encoding , self .errors )
596601 if self .qs_on_post :
597602 qs += '&' + self .qs_on_post
598- self .list = []
599603 query = urllib .parse .parse_qsl (
600604 qs , self .keep_blank_values , self .strict_parsing ,
601- encoding = self .encoding , errors = self .errors )
602- for key , value in query :
603- self .list . append ( MiniFieldStorage (key , value ))
605+ encoding = self .encoding , errors = self .errors ,
606+ max_num_fields = self . max_num_fields )
607+ self .list = [ MiniFieldStorage (key , value ) for key , value in query ]
604608 self .skip_lines ()
605609
606610 FieldStorageClass = None
@@ -614,9 +618,9 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
614618 if self .qs_on_post :
615619 query = urllib .parse .parse_qsl (
616620 self .qs_on_post , self .keep_blank_values , self .strict_parsing ,
617- encoding = self .encoding , errors = self .errors )
618- for key , value in query :
619- self .list .append (MiniFieldStorage (key , value ))
621+ encoding = self .encoding , errors = self .errors ,
622+ max_num_fields = self . max_num_fields )
623+ self .list .extend (MiniFieldStorage (key , value ) for key , value in query )
620624
621625 klass = self .FieldStorageClass or self .__class__
622626 first_line = self .fp .readline () # bytes
@@ -650,11 +654,23 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
650654 if 'content-length' in headers :
651655 del headers ['content-length' ]
652656
657+ # Propagate max_num_fields into the sub class appropriately
658+ sub_max_num_fields = self .max_num_fields
659+ if sub_max_num_fields is not None :
660+ sub_max_num_fields -= len (self .list )
661+
653662 part = klass (self .fp , headers , ib , environ , keep_blank_values ,
654663 strict_parsing ,self .limit - self .bytes_read ,
655- self .encoding , self .errors )
664+ self .encoding , self .errors , sub_max_num_fields )
665+
666+ max_num_fields = self .max_num_fields
667+ if max_num_fields is not None and part .list :
668+ max_num_fields -= len (part .list )
669+
656670 self .bytes_read += part .bytes_read
657671 self .list .append (part )
672+ if max_num_fields is not None and max_num_fields < len (self .list ):
673+ raise ValueError ('Max number of fields exceeded' )
658674 if part .done or self .bytes_read >= self .length > 0 :
659675 break
660676 self .skip_lines ()
0 commit comments