From 87d1770c182bb3e19229f1a652cabedce29b891e Mon Sep 17 00:00:00 2001 From: Eric Soroos Date: Wed, 2 Nov 2022 23:11:57 +0100 Subject: [PATCH] Fix null pointer dereference crash with malformed font --- Tests/fonts/fuzz_font-5203009437302784 | 10 ++++++++++ Tests/test_font_crash.py | 21 +++++++++++++++++++++ src/_imagingft.c | 6 ++++++ 3 files changed, 37 insertions(+) create mode 100644 Tests/fonts/fuzz_font-5203009437302784 create mode 100644 Tests/test_font_crash.py diff --git a/Tests/fonts/fuzz_font-5203009437302784 b/Tests/fonts/fuzz_font-5203009437302784 new file mode 100644 index 000000000..0465e48c2 --- /dev/null +++ b/Tests/fonts/fuzz_font-5203009437302784 @@ -0,0 +1,10 @@ +STARTFONT +FONT ÿ +SIZE 10 +FONTBOUNDINGBOX +CHARS +STARTCHAR +ENCODING +BBX 2 5 +ENDCHAR +ENDFONT diff --git a/Tests/test_font_crash.py b/Tests/test_font_crash.py new file mode 100644 index 000000000..020ddfcd9 --- /dev/null +++ b/Tests/test_font_crash.py @@ -0,0 +1,21 @@ +from PIL import Image, ImageDraw, ImageFont + +import pytest + +from .helper import skip_unless_feature + +class TestFontCrash: + def _fuzz_font(self, font): + # from fuzzers.fuzz_font + font.getbbox("ABC") + font.getmask("test text") + with Image.new(mode="RGBA", size=(200, 200)) as im: + draw = ImageDraw.Draw(im) + draw.multiline_textbbox((10, 10), "ABC\nAaaa", font, stroke_width=2) + draw.text((10, 10), "Test Text", font=font, fill="#000") + + @skip_unless_feature("freetype2") + def test_segfault(self): + with pytest.raises(OSError): + font= ImageFont.truetype('Tests/fonts/fuzz_font-5203009437302784') + self._fuzz_font(font) diff --git a/src/_imagingft.c b/src/_imagingft.c index b52d6353e..319098897 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -921,6 +921,12 @@ font_render(FontObject *self, PyObject *args) { yy = -(py + glyph_slot->bitmap_top); } + // Null buffer, is dereferenced in FT_Bitmap_Convert + if (!bitmap.buffer && bitmap.rows) { + return geterror(0x9D); // Bitmap missing + goto glyph_error; + } + /* convert non-8bpp bitmaps */ switch (bitmap.pixel_mode) { case FT_PIXEL_MODE_MONO: