Improper resource allocation In pillow
Description
Pillow PcfFontFile._load_bitmaps(): Image.frombytes() called without _decompression_bomb_check() — bomb protection bypass via PCF font loading
Description
PIL/PcfFontFile.py _load_bitmaps() (line 227) reads glyph dimensions from the PCF METRICS section and passes them directly to Image.frombytes() without calling Image._decompression_bomb_check(). Dimensions originate from unsigned 16-bit values:
xsize = right - left (max: 65535 − 0 = 65535) ysize = ascent + descent (max: 65535 + 65535 = 131070)
Maximum exploitable pixel count: 65,535 × 131,070 = 8,589,734,450 pixels — 48× the DecompressionBombError threshold.
Vulnerable code (PIL/PcfFontFile.py line 224–227):
for i in range(nbitmaps): xsize, ysize = metrics[i][:2] # from PCF METRICS — attacker-controlled b, e = offsets[i : i + 2] bitmaps.append( Image.frombytes("1", (xsize, ysize), data[b:e], "raw", mode, pad(xsize)) # ↑ NO _decompression_bomb_check()! )
Image.frombytes() calls Image.new() first (allocating the full C-heap buffer), then attempts to fill it. This creates two distinct attack paths:
Persistent attack: Provide matching bitmap data → frombytes() succeeds → image stored in font.glyph[ch] permanently
Transient attack: Provide a 148-byte PCF file with large declared dimensions but no data → Image.new() allocates the full buffer → ValueError → buffer freed → but the spike occurs before Python can respond
Steps to reproduce
Proof of Concept script:
#!/usr/bin/env python3 """PoC: PcfFontFile bomb bypass — 148-byte PCF → 23 MB allocation""" import io, struct, tracemalloc, warnings warnings.filterwarnings("ignore") from PIL.PcfFontFile import PcfFontFile from PIL.Image import _decompression_bomb_check, DecompressionBombWarning, DecompressionBombError ...
Expected output:
[Image.open() path] BLOCKED by DecompressionBombError [*] PCF file size : 148 bytes [*] Glyph size : 14000 x 14000 = 196,000,000 pixels [*] C-heap target : 23 MB (mode '1' = 1 bit/pixel) [!] CONFIRMED (transient): ValueError after allocation C-heap allocation of ~23 MB occurred before exception
Amplification table:
PCF file | Glyph dims | C-heap (mode '1') | Bomb check |
|---|---|---|---|
148 bytes | 14000 × 14000 | 23 MB (transient) | Bypassed |
148 bytes | 65535 × 131070 | 1.07 GB (transient) | Bypassed |
~512 MB | 65535 × 131070 | 1.07 GB (persistent) | Bypassed |
Impact
Availability: HIGH — up to 1.07 GB per glyph, no limit per font file
Confidentiality: None
Integrity: None
Any service loading PCF fonts from untrusted sources (e.g., PcfFontFile(fp)) is affected
PcfFontFile is never loaded via Image.open(), so the bomb check protection is completely absent from the entire PCF font loading path
Confirmed unpatched on python-pillow/Pillow main branch as of 2026-06-07
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Ecosystem | Component | Affected version | Patched versions |
|---|---|---|---|
debian 14 | 12.3.0-1 | ||
debian 13 | - | ||
debian 12 | - | ||
rpm rhel8 | 0:5.1.1-22.el8_10 | ||
pypi | 12.3.0 | ||
rpm rhel8.6 | 0:5.1.1-20.el8_6 | ||
rpm rhel8.4 | 0:5.1.1-15.el8_4.2 |
Aliases
References