Security fix for CVE-2026-54058, CVE-2026-59197

Resolves: RHEL-211857, RHEL-211848
This commit is contained in:
Lumír Balhar 2026-07-28 08:53:13 +00:00 committed by Lumir Balhar
parent 4a648bc0d4
commit 76f4b090f3
3 changed files with 147 additions and 1 deletions

45
CVE-2026-54058.patch Normal file
View File

@ -0,0 +1,45 @@
From 1701afc3d17717caed28e34e9ae1312773bb97f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lum=C3=ADr=20Balhar?= <lbalhar@redhat.com>
Date: Tue, 28 Jul 2026 08:49:17 +0000
Subject: [PATCH] CVE-2026-54058: Reject undersized stride when memory mapping
an image
Ensure map stride is at least one full row of pixels in PyImaging_MapBuffer.
Previously only recalculated stride when it was <= 0; a positive stride smaller
than xsize*pixelsize was accepted as-is, causing out-of-bounds reads.
Upstream fix: https://github.com/python-pillow/Pillow/pull/9719
---
src/map.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/map.c b/src/map.c
index 76b3160..ef36dd8 100644
--- a/src/map.c
+++ b/src/map.c
@@ -330,13 +330,18 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
return NULL;
}
- if (stride <= 0) {
+ {
+ int pixelsize;
if (!strcmp(mode, "L") || !strcmp(mode, "P"))
- stride = xsize;
+ pixelsize = 1;
else if (!strncmp(mode, "I;16", 4))
- stride = xsize * 2;
+ pixelsize = 2;
else
- stride = xsize * 4;
+ pixelsize = 4;
+
+ if (stride <= xsize * pixelsize) {
+ stride = xsize * pixelsize;
+ }
}
if (stride > 0 && ysize > INT_MAX / stride) {
--
2.55.0

89
CVE-2026-59197.patch Normal file
View File

@ -0,0 +1,89 @@
From 07c1fe0c758ecf46dcf97e44856a9a21a2a48a72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lum=C3=ADr=20Balhar?= <lbalhar@redhat.com>
Date: Tue, 28 Jul 2026 08:49:38 +0000
Subject: [PATCH] CVE-2026-59197: Validate size and rank when initializing
RankFilter
- Move size/rank validation into RankFilter.__init__ so errors are raised
at construction time rather than when filter() is called (PR #9661)
- Add check for excessively large filter sizes to prevent integer overflow
in rank filter buffer allocation (PR #9695)
- Update MedianFilter/MinFilter/MaxFilter to call super().__init__() to
inherit validation
- Add overflow guard in ImagingExpand for large margin values
Upstream fixes:
https://github.com/python-pillow/Pillow/pull/9661
https://github.com/python-pillow/Pillow/pull/9695
---
src/PIL/ImageFilter.py | 15 +++++++++------
src/libImaging/Filter.c | 6 ++++++
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/PIL/ImageFilter.py b/src/PIL/ImageFilter.py
index 735a008..1f458d5 100644
--- a/src/PIL/ImageFilter.py
+++ b/src/PIL/ImageFilter.py
@@ -76,6 +76,12 @@ class RankFilter(Filter):
name = "Rank"
def __init__(self, size, rank):
+ if size * size * 4 > (2**31 - 1):
+ raise ValueError("filter size too large")
+ if size % 2 != 1:
+ raise ValueError("bad filter size")
+ if not (0 <= rank < size * size):
+ raise ValueError("bad rank value")
self.size = size
self.rank = rank
@@ -96,8 +102,7 @@ class MedianFilter(RankFilter):
name = "Median"
def __init__(self, size=3):
- self.size = size
- self.rank = size*size//2
+ super().__init__(size, size*size//2)
class MinFilter(RankFilter):
@@ -110,8 +115,7 @@ class MinFilter(RankFilter):
name = "Min"
def __init__(self, size=3):
- self.size = size
- self.rank = 0
+ super().__init__(size, 0)
class MaxFilter(RankFilter):
@@ -124,8 +128,7 @@ class MaxFilter(RankFilter):
name = "Max"
def __init__(self, size=3):
- self.size = size
- self.rank = size*size-1
+ super().__init__(size, size*size-1)
class ModeFilter(Filter):
diff --git a/src/libImaging/Filter.c b/src/libImaging/Filter.c
index 6e4a005..1d492ac 100644
--- a/src/libImaging/Filter.c
+++ b/src/libImaging/Filter.c
@@ -46,6 +46,12 @@ ImagingExpand(Imaging imIn, int xmargin, int ymargin, int mode)
if (xmargin < 0 && ymargin < 0)
return (Imaging) ImagingError_ValueError("bad kernel size");
+ {
+ int margin = xmargin > ymargin ? xmargin : ymargin;
+ if (margin > 0 && margin > INT_MAX / (margin * (int)sizeof(FLOAT32)))
+ return (Imaging) ImagingError_ValueError("filter size too large");
+ }
+
imOut = ImagingNewDirty(
imIn->mode, imIn->xsize+2*xmargin, imIn->ysize+2*ymargin);
if (!imOut)
--
2.55.0

View File

@ -8,7 +8,7 @@
Name: python-%{srcname}
Version: 5.1.1
Release: 22%{?dist}
Release: 23%{?dist}
Summary: Python image processing library
# License: see http://www.pythonware.com/products/pil/license.htm
@ -133,6 +133,14 @@ Patch24: CVE-2026-54059_54060_55379.patch
# CVE-2026-55380 python-pillow: uncontrolled memory allocation in GdImageFile
# Upstream fix: https://github.com/python-pillow/Pillow/commit/f39b0ae6624eb2d7c5c5d651d9bb5fdbd96a8675
Patch25: CVE-2026-55380.patch
# CVE-2026-54058 python-pillow: out-of-bounds read via undersized stride when memory mapping McIdas AREA image
# Upstream fix: https://github.com/python-pillow/Pillow/pull/9719
Patch26: CVE-2026-54058.patch
# CVE-2026-59197 python-pillow: integer overflow in RankFilter leading to out-of-bounds memory access
# Upstream fixes:
# https://github.com/python-pillow/Pillow/pull/9661
# https://github.com/python-pillow/Pillow/pull/9695
Patch27: CVE-2026-59197.patch
BuildRequires: freetype-devel
BuildRequires: gcc
@ -277,6 +285,10 @@ popd
%changelog
* Mon Jul 28 2026 Lumír Balhar <lbalhar@redhat.com> - 5.1.1-23
- Security fix for CVE-2026-54058, CVE-2026-59197
Resolves: RHEL-211857, RHEL-211848
* Wed Jul 08 2026 Lumír Balhar <lbalhar@redhat.com> - 5.1.1-22
- Security fix for CVE-2026-54059, CVE-2026-54060, CVE-2026-55379, CVE-2026-55380
Resolves: RHEL-192830, RHEL-192770, RHEL-192684, RHEL-192731