|
1 | 1 | from __future__ import annotations |
| 2 | +import struct |
2 | 3 | import pytest |
| 4 | +from io import BytesIO |
3 | 5 |
|
4 | | -from PIL import Image, ImageDraw, ImageFont, features |
| 6 | +from PIL import Image, ImageDraw, ImageFont, features, _util |
5 | 7 |
|
6 | 8 | from .helper import assert_image_equal_tofile |
7 | 9 |
|
8 | | -pytestmark = pytest.mark.skipif( |
9 | | - features.check_module("freetype2"), |
10 | | - reason="PILfont superseded if FreeType is supported", |
11 | | -) |
| 10 | +original_core = ImageFont.core |
| 11 | + |
| 12 | + |
| 13 | +def setup_module(): |
| 14 | + if features.check_module("freetype2"): |
| 15 | + ImageFont.core = _util.DeferredError(ImportError) |
| 16 | + |
| 17 | + |
| 18 | +def teardown_module(): |
| 19 | + ImageFont.core = original_core |
12 | 20 |
|
13 | 21 |
|
14 | 22 | def test_default_font(): |
@@ -44,3 +52,23 @@ def test_textbbox(): |
44 | 52 | default_font = ImageFont.load_default() |
45 | 53 | assert d.textlength("test", font=default_font) == 24 |
46 | 54 | assert d.textbbox((0, 0), "test", font=default_font) == (0, 0, 24, 11) |
| 55 | + |
| 56 | + |
| 57 | +def test_decompression_bomb(): |
| 58 | + glyph = struct.pack(">hhhhhhhhhh", 1, 0, 0, 0, 256, 256, 0, 0, 256, 256) |
| 59 | + fp = BytesIO(b"PILfont\n\nDATA\n" + glyph * 256) |
| 60 | + |
| 61 | + font = ImageFont.ImageFont() |
| 62 | + font._load_pilfont_data(fp, Image.new("L", (256, 256))) |
| 63 | + with pytest.raises(Image.DecompressionBombError): |
| 64 | + font.getmask("A" * 1_000_000) |
| 65 | + |
| 66 | + |
| 67 | +@pytest.mark.timeout(4) |
| 68 | +def test_oom(): |
| 69 | + glyph = struct.pack(">hhhhhhhhhh", 1, 0, 0, 0, 32767, 32767, 0, 0, 32767, 32767) |
| 70 | + fp = BytesIO(b"PILfont\n\nDATA\n" + glyph * 256) |
| 71 | + |
| 72 | + font = ImageFont.ImageFont() |
| 73 | + font._load_pilfont_data(fp, Image.new("L", (1, 1))) |
| 74 | + font.getmask("A" * 1_000_000) |
0 commit comments