Skip to content

Commit

Permalink
Don't warn when CRLF is found after last boundary (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kludex authored Dec 1, 2024
1 parent 5b1aed8 commit c4fe4d3
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 0.0.19 (2024-11-30)

* Don't warn when CRLF is found after last boundary on `MultipartParser` [#193](https://github.com/Kludex/python-multipart/pull/193).

## 0.0.18 (2024-11-28)

* Hard break if found data after last boundary on `MultipartParser` [#189](https://github.com/Kludex/python-multipart/pull/189).
Expand Down
2 changes: 1 addition & 1 deletion python_multipart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__author__ = "Andrew Dunham"
__license__ = "Apache"
__copyright__ = "Copyright (c) 2012-2013, Andrew Dunham"
__version__ = "0.0.18"
__version__ = "0.0.19"

from .multipart import (
BaseParser,
Expand Down
4 changes: 4 additions & 0 deletions python_multipart/multipart.py
Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,10 @@ def data_callback(name: CallbackName, end_i: int, remaining: bool = False) -> No
i -= 1

elif state == MultipartState.END:
# Don't do anything if chunk ends with CRLF.
if c == CR and i + 1 < length and data[i + 1] == LF:
i += 2
continue
# Skip data after the last boundary.
self.logger.warning("Skipping data after last boundary")
i = length
Expand Down
2 changes: 1 addition & 1 deletion scripts/check
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ SOURCE_FILES="python_multipart multipart tests"

uvx ruff format --check --diff $SOURCE_FILES
uvx ruff check $SOURCE_FILES
uvx --with types-PyYAML mypy $SOURCE_FILES
uv run mypy $SOURCE_FILES
uvx check-sdist
26 changes: 26 additions & 0 deletions tests/test_multipart.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import logging
import os
import random
import sys
Expand All @@ -9,6 +10,7 @@
from typing import TYPE_CHECKING, cast
from unittest.mock import Mock

import pytest
import yaml

from python_multipart.decoders import Base64Decoder, QuotedPrintableDecoder
Expand Down Expand Up @@ -1248,6 +1250,30 @@ def on_file(f: FileProtocol) -> None:
f = FormParser("multipart/form-data", on_field=Mock(), on_file=on_file, boundary="boundary")
f.write(data.encode("latin-1"))

@pytest.fixture(autouse=True)
def inject_fixtures(self, caplog: pytest.LogCaptureFixture) -> None:
self._caplog = caplog

def test_multipart_parser_data_end_with_crlf_without_warnings(self) -> None:
"""This test makes sure that the parser does not handle when the data ends with a CRLF."""
data = (
"--boundary\r\n"
'Content-Disposition: form-data; name="file"; filename="filename.txt"\r\n'
"Content-Type: text/plain\r\n\r\n"
"hello\r\n"
"--boundary--\r\n"
)

files: list[File] = []

def on_file(f: FileProtocol) -> None:
files.append(cast(File, f))

f = FormParser("multipart/form-data", on_field=Mock(), on_file=on_file, boundary="boundary")
with self._caplog.at_level(logging.WARNING):
f.write(data.encode("latin-1"))
assert len(self._caplog.records) == 0

def test_max_size_multipart(self) -> None:
# Load test data.
test_file = "single_field_single_file.http"
Expand Down

0 comments on commit c4fe4d3

Please sign in to comment.