diff mbox series

[meta-python,wrynose,1/9] python3-pillow: Fix CVE-2026-54059 CVE-2026-54060 CVE-2026-55379

Message ID 20261016062323.251925-2-yurade@cisco.com
State New
Headers show
Series python3-pillow: Security fixes | expand

Commit Message

Yogita Urade Oct. 16, 2026, 6:23 a.m. UTC
This patch applies the upstream fix as referenced in [2], [3]
and [4], using the commit shown in [1].

[1] https://github.com/python-pillow/Pillow/commit/0a263e6264aa5399988d9acd3bbfbca2ca3ec77d
[2] https://nvd.nist.gov/vuln/detail/cve-2026-54059
[3] https://nvd.nist.gov/vuln/detail/CVE-2026-54060
[4] https://nvd.nist.gov/vuln/detail/cve-2026-55379

Signed-off-by: Yogita Urade <yurade@cisco.com>
---
 ...-54059_CVE-2026-54060_CVE-2026-55379.patch | 168 ++++++++++++++++++
 .../python/python3-pillow_12.2.0.bb           |   1 +
 2 files changed, 169 insertions(+)
 create mode 100644 meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54059_CVE-2026-54060_CVE-2026-55379.patch
diff mbox series

Patch

diff --git a/meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54059_CVE-2026-54060_CVE-2026-55379.patch b/meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54059_CVE-2026-54060_CVE-2026-55379.patch
new file mode 100644
index 0000000000..72a83a178e
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-pillow/CVE-2026-54059_CVE-2026-54060_CVE-2026-55379.patch
@@ -0,0 +1,168 @@ 
+From 7d525ae2ccf9109079f6f640ad88c8cb117853d9 Mon Sep 17 00:00:00 2001
+From: Andrew Murray <3112309+radarhere@users.noreply.github.com>
+Date: Tue, 23 Jun 2026 11:41:22 +1000
+Subject: [PATCH] Add decompression bomb checks to FontFile classes (#9711)
+
+CVE: CVE-2026-54059 CVE-2026-54060 CVE-2026-55379
+Upstream-Status: Backport [https://github.com/python-pillow/Pillow/commit/0a263e6264aa5399988d9acd3bbfbca2ca3ec77d]
+
+Backport Changes:
+- Wrynose 12.2.0 handles standard and jumbo PCF metrics in separate loops,
+  so the decompression-bomb check is added at both call sites in
+  src/PIL/PcfFontFile.py file, upstream’s shared append helper needs only
+  one check.
+
+(cherry picked from commit 0a263e6264aa5399988d9acd3bbfbca2ca3ec77d)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ Tests/test_font_bdf.py | 10 +++++++++-
+ Tests/test_font_pcf.py | 21 ++++++++++++++++++++-
+ Tests/test_fontfile.py |  7 +++++++
+ src/PIL/BdfFontFile.py |  1 +
+ src/PIL/FontFile.py    |  3 ++-
+ src/PIL/PcfFontFile.py |  2 ++
+ 6 files changed, 41 insertions(+), 3 deletions(-)
+diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py
+index 321dd8560..d5b080add 100644
+--- a/Tests/test_font_pcf.py
++++ b/Tests/test_font_pcf.py
+@@ -1,12 +1,13 @@
+ from __future__ import annotations
+ 
+ import os
++from io import BytesIO
+ from pathlib import Path
+ from typing import AnyStr
+ 
+ import pytest
+ 
+-from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile
++from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile, _binary
+ 
+ from .helper import (
+     assert_image_equal_tofile,
+@@ -117,3 +118,21 @@ def test_high_characters(request: pytest.FixtureRequest, tmp_path: Path) -> None
+     _test_high_characters(request, tmp_path, message)
+     # accept bytes instances.
+     _test_high_characters(request, tmp_path, message.encode("latin1"))
++
++
++def test_decompression_bomb() -> None:
++    with open(fontname, "rb") as fp:
++        data = fp.read()
++    b = BytesIO(
++        data[:900]
++        + _binary.o32le(0)  # jumbo format
++        + _binary.o32le(1)  # number of metrics
++        + _binary.o16le(0)  # left
++        + _binary.o16le(65535)  # right
++        + _binary.o16le(0)  # width
++        + _binary.o16le(0)  # ascent
++        + _binary.o16le(65535)  # descent
++        + _binary.o16le(0)  # attributes
++    )
++    with pytest.raises(Image.DecompressionBombError):
++        PcfFontFile.PcfFontFile(b)
+diff --git a/src/PIL/PcfFontFile.py b/src/PIL/PcfFontFile.py
+index b923293b0..52947ff04 100644
+--- a/src/PIL/PcfFontFile.py
++++ b/src/PIL/PcfFontFile.py
+@@ -170,6 +170,7 @@ class PcfFontFile(FontFile.FontFile):
+                 descent = i8(fp.read(1)) - 128
+                 xsize = right - left
+                 ysize = ascent + descent
++                Image._decompression_bomb_check((xsize, ysize))
+                 append((xsize, ysize, left, right, width, ascent, descent, 0))
+ 
+         else:
+@@ -183,6 +184,7 @@ class PcfFontFile(FontFile.FontFile):
+                 attributes = i16(fp.read(2))
+                 xsize = right - left
+                 ysize = ascent + descent
++                Image._decompression_bomb_check((xsize, ysize))
+                 append((xsize, ysize, left, right, width, ascent, descent, attributes))
+ 
+         return metrics
+
+diff --git a/Tests/test_font_bdf.py b/Tests/test_font_bdf.py
+index b4155c8793b..033b5f8fbd5 100644
+--- a/Tests/test_font_bdf.py
++++ b/Tests/test_font_bdf.py
+@@ -4,7 +4,7 @@
+ 
+ import pytest
+ 
+-from PIL import BdfFontFile, FontFile
++from PIL import BdfFontFile, FontFile, Image
+ 
+ filename = "Tests/images/courB08.bdf"
+ 
+@@ -24,6 +24,14 @@ def test_zero_width_chars() -> None:
+     BdfFontFile.BdfFontFile(io.BytesIO(data))
+ 
+ 
++def test_decompression_bomb() -> None:
++    with open(filename, "rb") as fp:
++        data = fp.read()
++    b = io.BytesIO(data.replace(b"BBX 1 1", b"BBX 13378 13378"))
++    with pytest.raises(Image.DecompressionBombError):
++        BdfFontFile.BdfFontFile(b)
++
++
+ def test_invalid_file() -> None:
+     with open("Tests/images/flower.jpg", "rb") as fp:
+         with pytest.raises(SyntaxError):
+
+diff --git a/Tests/test_fontfile.py b/Tests/test_fontfile.py
+index 1a9069fd892..bf857e230b8 100644
+--- a/Tests/test_fontfile.py
++++ b/Tests/test_fontfile.py
+@@ -30,6 +30,13 @@ def test_compile() -> None:
+     assert font.ysize == 2
+ 
+ 
++def test_decompression_bomb() -> None:
++    font = FontFile.FontFile()
++    font.glyph[0] = ((0, 0), (0, 0, 0, 0), (0, 0, 10000, 10000), Image.new("L", (0, 0)))
++    with pytest.raises(Image.DecompressionBombError):
++        font.compile()
++
++
+ def test_save(tmp_path: Path) -> None:
+     tempname = str(tmp_path / "temp.pil")
+ 
+
+diff --git a/src/PIL/BdfFontFile.py b/src/PIL/BdfFontFile.py
+index 1c8c28ff038..098779bfd6e 100644
+--- a/src/PIL/BdfFontFile.py
++++ b/src/PIL/BdfFontFile.py
+@@ -70,6 +70,7 @@ def bdf_char(
+     # and x and y displacement (BBxoff0, BByoff0)
+     # of the lower left corner from the origin of the character.
+     width, height, x_disp, y_disp = (int(p) for p in props["BBX"].split())
++    Image._decompression_bomb_check((width, height))
+ 
+     # The word DWIDTH
+     # followed by the width in x and y of the character in device pixels.
+
+diff --git a/src/PIL/FontFile.py b/src/PIL/FontFile.py
+index 341431d3f45..c3be4ae3ddd 100644
+--- a/src/PIL/FontFile.py
++++ b/src/PIL/FontFile.py
+@@ -74,7 +74,7 @@ def compile(self) -> None:
+             if glyph:
+                 d, dst, src, im = glyph
+                 h = max(h, src[3] - src[1])
+-                w = w + (src[2] - src[0])
++                w += src[2] - src[0]
+                 if w > WIDTH:
+                     lines += 1
+                     w = src[2] - src[0]
+@@ -89,6 +89,7 @@ def compile(self) -> None:
+         self.ysize = h
+ 
+         # paste glyphs into bitmap
++        Image._decompression_bomb_check((xsize, ysize))
+         self.bitmap = Image.new("1", (xsize, ysize))
+         self.metrics: list[
+             tuple[tuple[int, int], tuple[int, int, int, int], tuple[int, int, int, int]]
diff --git a/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb b/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb
index d5c65fbd11..aa7de55fab 100644
--- a/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb
+++ b/meta-python/recipes-devtools/python/python3-pillow_12.2.0.bb
@@ -9,6 +9,7 @@  SRC_URI = "git://github.com/python-pillow/Pillow.git;branch=main;protocol=https;
            file://0001-support-cross-compiling.patch \
            file://CVE-2026-54058.patch \
            file://CVE-2026-59204.patch \
+           file://CVE-2026-54059_CVE-2026-54060_CVE-2026-55379.patch \
            "
 SRCREV = "3c41c095064200a02672d89cc5ff629eaf4b0d4f"