4141)
4242from .helpers import CHAR , TOKEN , parse_mimetype , reify
4343from .http import HeadersParser
44+ from .http_exceptions import BadHttpMessage
4445from .log import internal_logger
4546from .payload import (
4647 JsonPayload ,
@@ -658,7 +659,14 @@ class MultipartReader:
658659 #: Body part reader class for non multipart/* content types.
659660 part_reader_cls = BodyPartReader
660661
661- def __init__ (self , headers : Mapping [str , str ], content : StreamReader ) -> None :
662+ def __init__ (
663+ self ,
664+ headers : Mapping [str , str ],
665+ content : StreamReader ,
666+ * ,
667+ max_field_size : int = 8190 ,
668+ max_headers : int = 128 ,
669+ ) -> None :
662670 self ._mimetype = parse_mimetype (headers [CONTENT_TYPE ])
663671 assert self ._mimetype .type == "multipart" , "multipart/* content type expected"
664672 if "boundary" not in self ._mimetype .parameters :
@@ -669,8 +677,10 @@ def __init__(self, headers: Mapping[str, str], content: StreamReader) -> None:
669677 self .headers = headers
670678 self ._boundary = ("--" + self ._get_boundary ()).encode ()
671679 self ._content = content
672- self ._default_charset : Optional [str ] = None
673- self ._last_part : Optional [Union ["MultipartReader" , BodyPartReader ]] = None
680+ self ._default_charset : str | None = None
681+ self ._last_part : MultipartReader | BodyPartReader | None = None
682+ self ._max_field_size = max_field_size
683+ self ._max_headers = max_headers
674684 self ._at_eof = False
675685 self ._at_bof = True
676686 self ._unread : List [bytes ] = []
@@ -770,7 +780,12 @@ def _get_part_reader(
770780 if mimetype .type == "multipart" :
771781 if self .multipart_reader_cls is None :
772782 return type (self )(headers , self ._content )
773- return self .multipart_reader_cls (headers , self ._content )
783+ return self .multipart_reader_cls (
784+ headers ,
785+ self ._content ,
786+ max_field_size = self ._max_field_size ,
787+ max_headers = self ._max_headers ,
788+ )
774789 else :
775790 return self .part_reader_cls (
776791 self ._boundary ,
@@ -832,12 +847,14 @@ async def _read_boundary(self) -> None:
832847 async def _read_headers (self ) -> "CIMultiDictProxy[str]" :
833848 lines = []
834849 while True :
835- chunk = await self ._content .readline ()
850+ chunk = await self ._content .readline (max_line_length = self . _max_field_size )
836851 chunk = chunk .rstrip (b"\r \n " )
837852 lines .append (chunk )
838853 if not chunk :
839854 break
840- parser = HeadersParser ()
855+ if len (lines ) > self ._max_headers :
856+ raise BadHttpMessage ("Too many headers received" )
857+ parser = HeadersParser (max_field_size = self ._max_field_size )
841858 headers , raw_headers = parser .parse_headers (lines )
842859 return headers
843860
0 commit comments