@@ -1096,19 +1096,34 @@ def parse_response_start_line(line: str) -> ResponseStartLine:
10961096# It has also been modified to support valueless parameters as seen in
10971097# websocket extension negotiations, and to support non-ascii values in
10981098# RFC 2231/5987 format.
1099+ #
1100+ # _parseparam has been further modified with the logic from
1101+ # https://github.com/python/cpython/pull/136072/files
1102+ # to avoid quadratic behavior when parsing semicolons in quoted strings.
1103+ #
1104+ # TODO: See if we can switch to email.message.Message for this functionality.
1105+ # This is the suggested replacement for the cgi.py module now that cgi has
1106+ # been removed from recent versions of Python. We need to verify that
1107+ # the email module is consistent with our existing behavior (and all relevant
1108+ # RFCs for multipart/form-data) before making this change.
10991109
11001110
11011111def _parseparam (s : str ) -> Generator [str , None , None ]:
1102- while s [:1 ] == ";" :
1103- s = s [1 :]
1104- end = s .find (";" )
1105- while end > 0 and (s .count ('"' , 0 , end ) - s .count ('\\ "' , 0 , end )) % 2 :
1106- end = s .find (";" , end + 1 )
1112+ start = 0
1113+ while s .find (";" , start ) == start :
1114+ start += 1
1115+ end = s .find (";" , start )
1116+ ind , diff = start , 0
1117+ while end > 0 :
1118+ diff += s .count ('"' , ind , end ) - s .count ('\\ "' , ind , end )
1119+ if diff % 2 == 0 :
1120+ break
1121+ end , ind = ind , s .find (";" , end + 1 )
11071122 if end < 0 :
11081123 end = len (s )
1109- f = s [:end ]
1124+ f = s [start :end ]
11101125 yield f .strip ()
1111- s = s [ end :]
1126+ start = end
11121127
11131128
11141129def _parse_header (line : str ) -> Tuple [str , Dict [str , str ]]:
0 commit comments