diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index 49cdd8e..f7f7f9f 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -1203,6 +1203,11 @@ def data_callback(name: CallbackName, end_i: int, remaining: bool = False) -> No i -= 1 elif state == MultipartState.START_BOUNDARY: + if index == 0 and data.startswith(boundary[2:], i, length): + index = boundary_length - 2 + i += index + continue + # Check to ensure that the last 2 characters in our boundary # are CRLF. if index == boundary_length - 2: diff --git a/tests/test_multipart.py b/tests/test_multipart.py index 949d70c..292cd21 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -850,6 +850,22 @@ def test_content_transfer_encoding_is_case_insensitive(content_transfer_encoding assert file.file_object.read() == b"Test" +def test_multipart_opening_boundary_max_size() -> None: + data = b"--boundary\r\n\r\nvalue\r\n--boundary--" + max_size = 9 + events: list[str] = [] + parser = MultipartParser( + b"boundary", + {"on_part_begin": lambda: events.append("begin"), "on_end": lambda: events.append("end")}, + max_size=max_size, + ) + assert parser.write(data) == max_size + parser.max_size = len(data) # type: ignore[assignment] # mypy narrows max_size to float & Number. + assert parser.write(data[max_size:]) == len(data) - max_size + parser.finalize() + assert events == ["begin", "end"] + + @parametrize_class class TestFormParser(unittest.TestCase): def make(self, boundary: str | bytes, config: dict[str, Any] = {}) -> None: