diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py index 0a4abdae1b6..974d4b7a3ad 100644 --- a/Tests/test_image_filter.py +++ b/Tests/test_image_filter.py @@ -236,40 +236,24 @@ def test_consistency_i16_high_byte(mode: str) -> None: assert im.getpixel((4, 4)) == 1000 -@pytest.mark.parametrize( - "radius", - ( - -2, - (-2, -2), - (-2, 2), - (2, -2), - ), -) -def test_invalid_box_blur_filter(radius: int | tuple[int, int]) -> None: - with pytest.raises(ValueError): - ImageFilter.BoxBlur(radius) +@pytest.mark.parametrize("size", (-1, math.nan, math.inf, 2**31)) +def test_invalid_box_blur_filter(size: int) -> None: + for radius in (size, (size, size), (size, 1), (1, size)): + with pytest.raises(ValueError, match="radius"): + ImageFilter.BoxBlur(radius) - im = hopper() - box_blur_filter = ImageFilter.BoxBlur(2) - box_blur_filter.radius = radius - with pytest.raises(ValueError): - im.filter(box_blur_filter) + im = hopper() + box_blur_filter = ImageFilter.BoxBlur(2) + box_blur_filter.radius = radius + with pytest.raises(ValueError, match="radius"): + im.filter(box_blur_filter) -@pytest.mark.parametrize( - "radius", - ( - math.nan, - (math.nan, 1), - (1, math.nan), - math.inf, - (1, math.inf), - (math.inf, 1), - ), -) -def test_box_blur_non_finite_radius(radius: float | tuple[float, float]) -> None: - with pytest.raises(ValueError, match="radius must be a finite number >= 0"): - ImageFilter.BoxBlur(radius) +@pytest.mark.parametrize("radius", (math.nan, math.inf, 2**31)) +def test_invalid_gaussian_blur_filter(radius: int) -> None: + im = hopper() + with pytest.raises(ValueError, match="radius"): + im.filter(ImageFilter.GaussianBlur(radius)) def test_rankfilter_size_1() -> None: diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index 5d6a1d5ec6c..9fc66a232fa 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -17,7 +17,6 @@ from __future__ import annotations import abc -import math from typing import cast TYPE_CHECKING = False @@ -221,8 +220,11 @@ class BoxBlur(MultibandFilter): def __init__(self, radius: float | Sequence[float]) -> None: xy = radius if isinstance(radius, (tuple, list)) else (radius, radius) - if not all(math.isfinite(value) and value >= 0 for value in xy): - msg = "radius must be a finite number >= 0" + if not all(value >= 0 for value in xy): + msg = "radius must be >= 0" + raise ValueError(msg) + if any(value >= 2**31 for value in xy): + msg = "radius too large" raise ValueError(msg) self.radius = radius diff --git a/src/libImaging/BoxBlur.c b/src/libImaging/BoxBlur.c index 58eaa075877..b1a8fd04a19 100644 --- a/src/libImaging/BoxBlur.c +++ b/src/libImaging/BoxBlur.c @@ -241,9 +241,14 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float xradius, float yradius, int n) if (n < 1) { return ImagingError_ValueError("number of passes must be greater than zero"); } - if (xradius < 0 || yradius < 0) { + /* Negated comparisons, so that NaN is rejected as well. */ + if (!(xradius >= 0) || !(yradius >= 0)) { return ImagingError_ValueError("radius must be >= 0"); } + /* 2**31 and above cannot be converted to an int. */ + if (xradius >= 2147483648.0f || yradius >= 2147483648.0f) { + return ImagingError_ValueError("radius too large"); + } if (imIn->mode != imOut->mode || imIn->type != imOut->type || imIn->bands != imOut->bands || imIn->xsize != imOut->xsize ||