From e79f9df52165f60830a16fc1e040495ebe9155f9 Mon Sep 17 00:00:00 2001 From: Jonnas Figueiredo <125215987+JonnasFigueiredo@users.noreply.github.com> Date: Tue, 25 Aug 2026 20:50:17 -0300 Subject: [PATCH 1/3] Reject non-finite radius in BoxBlur BoxBlur only checked `radius < 0`, so a NaN or infinite radius passed the Python-level validation (`nan < 0` is False) and reached the C `box_blur`, causing a heap-buffer-overflow. Validate that the radius is a finite, non-negative number and raise ValueError, as is already done for negative radii. --- Tests/test_image_filter.py | 14 ++++++++++++++ src/PIL/ImageFilter.py | 5 +++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py index 4fa24e2f9c5..2ab3fa61bfb 100644 --- a/Tests/test_image_filter.py +++ b/Tests/test_image_filter.py @@ -235,6 +235,20 @@ def test_invalid_box_blur_filter(radius: int | tuple[int, int]) -> None: im.filter(box_blur_filter) +@pytest.mark.parametrize( + "radius", + ( + float("nan"), + float("inf"), + (float("nan"), 2), + (2, float("inf")), + ), +) +def test_box_blur_non_finite_radius(radius: float | tuple[float, float]) -> None: + with pytest.raises(ValueError): + ImageFilter.BoxBlur(radius) + + def test_rankfilter_size_1() -> None: im = Image.new("L", (3, 3), 128) diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py index b5229cad92b..42ce646cc6d 100644 --- a/src/PIL/ImageFilter.py +++ b/src/PIL/ImageFilter.py @@ -17,6 +17,7 @@ from __future__ import annotations import abc +import math from typing import cast TYPE_CHECKING = False @@ -222,8 +223,8 @@ class BoxBlur(MultibandFilter): def __init__(self, radius: float | Sequence[float]) -> None: xy = radius if isinstance(radius, (tuple, list)) else (radius, radius) - if xy[0] < 0 or xy[1] < 0: - msg = "radius must be >= 0" + if not all(math.isfinite(value) and value >= 0 for value in xy): + msg = "radius must be a finite number >= 0" raise ValueError(msg) self.radius = radius From 9f1cce385d96b291b11b8be5fb6cd3d7e30ad2f8 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 29 Aug 2026 16:30:04 +1000 Subject: [PATCH 2/3] Use direct values --- Tests/test_image_filter.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py index 2ab3fa61bfb..464718d8011 100644 --- a/Tests/test_image_filter.py +++ b/Tests/test_image_filter.py @@ -1,5 +1,7 @@ from __future__ import annotations +import math + import pytest from PIL import Image, ImageFilter @@ -238,10 +240,12 @@ def test_invalid_box_blur_filter(radius: int | tuple[int, int]) -> None: @pytest.mark.parametrize( "radius", ( - float("nan"), - float("inf"), - (float("nan"), 2), - (2, float("inf")), + 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: From 30dbfa82a597008d927488d8de08ef21cb62c51c Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Thu, 3 Sep 2026 12:09:35 +1000 Subject: [PATCH 3/3] Check specific error message --- Tests/test_image_filter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py index 464718d8011..7f228f872e6 100644 --- a/Tests/test_image_filter.py +++ b/Tests/test_image_filter.py @@ -249,7 +249,7 @@ def test_invalid_box_blur_filter(radius: int | tuple[int, int]) -> None: ), ) def test_box_blur_non_finite_radius(radius: float | tuple[float, float]) -> None: - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="radius must be a finite number >= 0"): ImageFilter.BoxBlur(radius)