diff --git a/Tests/test_imagemorph.py b/Tests/test_imagemorph.py index 515e29cead9..ca192a809c4 100644 --- a/Tests/test_imagemorph.py +++ b/Tests/test_imagemorph.py @@ -7,7 +7,7 @@ from PIL import Image, ImageMorph, _imagingmorph -from .helper import assert_image_equal_tofile, hopper +from .helper import assert_image_equal_tofile, hopper, timeout_unless_slower_valgrind def string_to_img(image_string: str) -> Image.Image: @@ -266,16 +266,18 @@ def test_unknown_pattern() -> None: ImageMorph.LutBuilder(op_name="unknown") -def test_pattern_syntax_error() -> None: +@pytest.mark.parametrize( + "pattern", ("a pattern with a syntax error", "4:(" + "X" * 30000) +) +@timeout_unless_slower_valgrind(1) +def test_pattern_syntax_error(pattern: str) -> None: # Arrange lb = ImageMorph.LutBuilder(op_name="corner") - new_patterns = ["a pattern with a syntax error"] + new_patterns = [pattern] lb.add_patterns(new_patterns) # Act / Assert - with pytest.raises( - Exception, match='Syntax error in pattern "a pattern with a syntax error"' - ): + with pytest.raises(Exception, match='Syntax error in pattern "'): lb.build_lut() diff --git a/docs/releasenotes/12.0.0.rst b/docs/releasenotes/12.0.0.rst index e21c243ea55..41edea31844 100644 --- a/docs/releasenotes/12.0.0.rst +++ b/docs/releasenotes/12.0.0.rst @@ -150,3 +150,10 @@ others prepare for 3.14, and to ensure Pillow could be used immediately at the r of 3.14.0 final (2025-10-07, :pep:`745`). Pillow 12.0.0 now officially supports Python 3.14. + +ImageMorph operations must have length 1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Valid ImageMorph operations are 4, N, 1 and M. By limiting the length to 1 character +within Pillow, long execution times can be avoided if a user provided long pattern +strings. Reported by Jang Choi. diff --git a/src/PIL/ImageMorph.py b/src/PIL/ImageMorph.py index f0a066b5bd8..bd70aff7b48 100644 --- a/src/PIL/ImageMorph.py +++ b/src/PIL/ImageMorph.py @@ -150,7 +150,7 @@ def build_lut(self) -> bytearray: # Parse and create symmetries of the patterns strings for p in self.patterns: - m = re.search(r"(\w*):?\s*\((.+?)\)\s*->\s*(\d)", p.replace("\n", "")) + m = re.search(r"(\w):?\s*\((.+?)\)\s*->\s*(\d)", p.replace("\n", "")) if not m: msg = 'Syntax error in pattern "' + p + '"' raise Exception(msg)