From fc055dbef875b477c27196e10c61f98aeb23d62c Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Fri, 10 Nov 2023 15:39:41 +0100 Subject: [PATCH] CVE-2023-44271 --- docs/reference/ImageFont.rst | 9 +++++++++ src/PIL/ImageFont.py | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/docs/reference/ImageFont.rst b/docs/reference/ImageFont.rst index 76fde44..21b9d9d 100644 --- a/docs/reference/ImageFont.rst +++ b/docs/reference/ImageFont.rst @@ -17,6 +17,15 @@ OpenType fonts (as well as other font formats supported by the FreeType library). For earlier versions, TrueType support is only available as part of the imToolkit package +.. warning:: + To protect against potential DOS attacks when using arbitrary strings as + text input, Pillow will raise a ``ValueError`` if the number of characters + is over a certain limit, :py:data:`MAX_STRING_LENGTH`. + + This threshold can be changed by setting + :py:data:`MAX_STRING_LENGTH`. It can be disabled by setting + ``ImageFont.MAX_STRING_LENGTH = None``. + Example ------- diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index f3b55e0..7e7b62f 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -39,6 +39,8 @@ class _imagingft_not_installed(object): def __getattr__(self, id): raise ImportError("The _imagingft C module is not installed") +MAX_STRING_LENGTH = 1_000_000 + try: from . import _imagingft as core @@ -46,6 +48,12 @@ except ImportError: core = _imagingft_not_installed() +def _string_length_check(text): + if MAX_STRING_LENGTH is not None and len(text) > MAX_STRING_LENGTH: + msg = "too many characters in string" + raise ValueError(msg) + + # FIXME: add support for pilfont2 format (see FontFile.py) # -------------------------------------------------------------------- @@ -109,6 +117,7 @@ class ImageFont(object): self.font = Image.core.font(image.im, data) def getsize(self, text, *args, **kwargs): + _string_length_check(text) return self.font.getsize(text) def getmask(self, text, mode="", *args, **kwargs): @@ -154,6 +163,7 @@ class FreeTypeFont(object): return self.font.ascent, self.font.descent def getsize(self, text, direction=None, features=None): + _string_length_check(text) size, offset = self.font.getsize(text, direction, features) return (size[0] + offset[0], size[1] + offset[1]) @@ -164,6 +174,7 @@ class FreeTypeFont(object): return self.getmask2(text, mode, direction=direction, features=features)[0] def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, features=None, *args, **kwargs): + _string_length_check(text) size, offset = self.font.getsize(text, direction, features) im = fill("L", size, 0) self.font.render(text, im.id, mode == "1", direction, features) @@ -205,6 +216,7 @@ class TransposedFont(object): self.orientation = orientation # any 'transpose' argument, or None def getsize(self, text, *args, **kwargs): + _string_length_check(text) w, h = self.font.getsize(text) if self.orientation in (Image.ROTATE_90, Image.ROTATE_270): return h, w -- 2.41.0