From 57a5f76e6d78f280fa7cd666bff32fe3452f140b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 2 Sep 2025 21:09:07 +1000 Subject: [PATCH 1/3] Removed unused split --- src/PIL/ImageFont.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index a2bf9ccf9..446160c2f 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -129,7 +129,7 @@ class ImageFont: if file.readline() != b"PILfont\n": msg = "Not a PILfont file" raise SyntaxError(msg) - file.readline().split(b";") + file.readline() self.info = [] # FIXME: should be a dictionary while True: s = file.readline() From 485d9884cf7a3cd2ceedc91df9c8625454b6d8f5 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 2 Sep 2025 21:24:57 +1000 Subject: [PATCH 2/3] Limit length of read operation --- Tests/test_imagefont.py | 5 +++++ src/PIL/ImageFont.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 4565d35ba..08034ad0d 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -492,6 +492,11 @@ def test_stroke_mask() -> None: assert mask.getpixel((42, 5)) == 255 +def test_load_invalid_file() -> None: + with pytest.raises(SyntaxError, match="Not a PILfont file"): + ImageFont.load("Tests/images/1_trns.png") + + def test_load_when_image_not_found() -> None: with tempfile.NamedTemporaryFile(delete=False) as tmp: pass diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 446160c2f..df2f00882 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -126,7 +126,7 @@ class ImageFont: def _load_pilfont_data(self, file: IO[bytes], image: Image.Image) -> None: # read PILfont header - if file.readline() != b"PILfont\n": + if file.read(8) != b"PILfont\n": msg = "Not a PILfont file" raise SyntaxError(msg) file.readline() From caacd38e1be189ed5a9d9ba892e595cbdfaa551b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 2 Sep 2025 21:32:13 +1000 Subject: [PATCH 3/3] Raise mode error before reading --- Tests/test_imagefontpil.py | 8 ++++++++ src/PIL/ImageFont.py | 10 +++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Tests/test_imagefontpil.py b/Tests/test_imagefontpil.py index 3eb98d379..8c1cb3f58 100644 --- a/Tests/test_imagefontpil.py +++ b/Tests/test_imagefontpil.py @@ -30,6 +30,14 @@ def test_default_font(font: ImageFont.ImageFont) -> None: assert_image_equal_tofile(im, "Tests/images/default_font.png") +def test_invalid_mode() -> None: + font = ImageFont.ImageFont() + fp = BytesIO() + with Image.open("Tests/images/hopper.png") as im: + with pytest.raises(TypeError, match="invalid font image mode"): + font._load_pilfont_data(fp, im) + + def test_without_freetype() -> None: original_core = ImageFont.core if features.check_module("freetype2"): diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index df2f00882..92eb763a5 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -125,6 +125,11 @@ class ImageFont: image.close() def _load_pilfont_data(self, file: IO[bytes], image: Image.Image) -> None: + # check image + if image.mode not in ("1", "L"): + msg = "invalid font image mode" + raise TypeError(msg) + # read PILfont header if file.read(8) != b"PILfont\n": msg = "Not a PILfont file" @@ -140,11 +145,6 @@ class ImageFont: # read PILfont metrics data = file.read(256 * 20) - # check image - if image.mode not in ("1", "L"): - msg = "invalid font image mode" - raise TypeError(msg) - image.load() self.font = Image.core.font(image.im, data)