diff --git a/Tests/fonts/fuzz_font-5203009437302784 b/Tests/fonts/fuzz_font-5203009437302784 new file mode 100644 index 00000000000..0465e48c204 --- /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/oss-fuzz/test_fuzzers.py b/Tests/oss-fuzz/test_fuzzers.py index 629e9ac00d4..dc111c38b36 100644 --- a/Tests/oss-fuzz/test_fuzzers.py +++ b/Tests/oss-fuzz/test_fuzzers.py @@ -57,6 +57,6 @@ def test_fuzz_fonts(path): with open(path, "rb") as f: try: fuzzers.fuzz_font(f.read()) - except (Image.DecompressionBombError, Image.DecompressionBombWarning): + except (Image.DecompressionBombError, Image.DecompressionBombWarning, OSError): pass assert True diff --git a/Tests/test_font_crash.py b/Tests/test_font_crash.py new file mode 100644 index 00000000000..27663f396ea --- /dev/null +++ b/Tests/test_font_crash.py @@ -0,0 +1,22 @@ +import pytest + +from PIL import Image, ImageDraw, ImageFont + +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 b52d6353ebc..0db17a5a6db 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) { + PyErr_SetString(PyExc_OSError, "Bitmap missing for glyph"); + goto glyph_error; + } + /* convert non-8bpp bitmaps */ switch (bitmap.pixel_mode) { case FT_PIXEL_MODE_MONO: