@@ -311,7 +311,8 @@ class FieldStorage:
311311 """
312312 def __init__ (self , fp = None , headers = None , outerboundary = b'' ,
313313 environ = os .environ , keep_blank_values = 0 , strict_parsing = 0 ,
314- limit = None , encoding = 'utf-8' , errors = 'replace' ):
314+ limit = None , encoding = 'utf-8' , errors = 'replace' ,
315+ max_num_fields = None ):
315316 """Constructor. Read multipart/* until last part.
316317
317318 Arguments, all optional:
@@ -351,10 +352,14 @@ def __init__(self, fp=None, headers=None, outerboundary=b'',
351352 for the page sending the form (content-type : meta http-equiv or
352353 header)
353354
355+ max_num_fields: int. If set, then __init__ throws a ValueError
356+ if there are more than n fields read by parse_qsl().
357+
354358 """
355359 method = 'GET'
356360 self .keep_blank_values = keep_blank_values
357361 self .strict_parsing = strict_parsing
362+ self .max_num_fields = max_num_fields
358363 if 'REQUEST_METHOD' in environ :
359364 method = environ ['REQUEST_METHOD' ].upper ()
360365 self .qs_on_post = None
@@ -578,12 +583,11 @@ def read_urlencoded(self):
578583 qs = qs .decode (self .encoding , self .errors )
579584 if self .qs_on_post :
580585 qs += '&' + self .qs_on_post
581- self .list = []
582586 query = urllib .parse .parse_qsl (
583587 qs , self .keep_blank_values , self .strict_parsing ,
584- encoding = self .encoding , errors = self .errors )
585- for key , value in query :
586- self .list . append ( MiniFieldStorage (key , value ))
588+ encoding = self .encoding , errors = self .errors ,
589+ max_num_fields = self . max_num_fields )
590+ self .list = [ MiniFieldStorage (key , value ) for key , value in query ]
587591 self .skip_lines ()
588592
589593 FieldStorageClass = None
@@ -597,9 +601,9 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
597601 if self .qs_on_post :
598602 query = urllib .parse .parse_qsl (
599603 self .qs_on_post , self .keep_blank_values , self .strict_parsing ,
600- encoding = self .encoding , errors = self .errors )
601- for key , value in query :
602- self .list .append (MiniFieldStorage (key , value ))
604+ encoding = self .encoding , errors = self .errors ,
605+ max_num_fields = self . max_num_fields )
606+ self .list .extend (MiniFieldStorage (key , value ) for key , value in query )
603607
604608 klass = self .FieldStorageClass or self .__class__
605609 first_line = self .fp .readline () # bytes
@@ -633,11 +637,23 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
633637 if 'content-length' in headers :
634638 del headers ['content-length' ]
635639
640+ # Propagate max_num_fields into the sub class appropriately
641+ sub_max_num_fields = self .max_num_fields
642+ if sub_max_num_fields is not None :
643+ sub_max_num_fields -= len (self .list )
644+
636645 part = klass (self .fp , headers , ib , environ , keep_blank_values ,
637646 strict_parsing ,self .limit - self .bytes_read ,
638- self .encoding , self .errors )
647+ self .encoding , self .errors , sub_max_num_fields )
648+
649+ max_num_fields = self .max_num_fields
650+ if max_num_fields is not None and part .list :
651+ max_num_fields -= len (part .list )
652+
639653 self .bytes_read += part .bytes_read
640654 self .list .append (part )
655+ if max_num_fields is not None and max_num_fields < len (self .list ):
656+ raise ValueError ('Max number of fields exceeded' )
641657 if part .done or self .bytes_read >= self .length > 0 :
642658 break
643659 self .skip_lines ()
0 commit comments