diff --git a/SOURCES/gimp-CVE-2026-4150.patch b/SOURCES/gimp-CVE-2026-4150.patch new file mode 100644 index 0000000..23d7a59 --- /dev/null +++ b/SOURCES/gimp-CVE-2026-4150.patch @@ -0,0 +1,114 @@ +diff -urNp a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c +--- a/plug-ins/file-psd/psd-load.c 2026-05-12 09:23:16.334611459 +0200 ++++ b/plug-ins/file-psd/psd-load.c 2026-05-12 13:04:29.851721411 +0200 +@@ -1516,7 +1516,7 @@ add_merged_image (const gint32 image_id + guint16 total_channels; + guint16 *rle_pack_len[MAX_CHANNELS]; + guint32 alpha_id; +- gint32 layer_size; ++ gsize layer_size; + gint32 layer_id = -1; + gint32 channel_id = -1; + gint32 active_layer; +@@ -1526,7 +1526,6 @@ add_merged_image (const gint32 image_id + gint rowi; /* Row index */ + gint lyr_count; + gint offset; +- gint i; + gboolean alpha_visible; + GimpDrawable *drawable; + GimpPixelRgn pixel_rgn; +@@ -1639,11 +1638,11 @@ add_merged_image (const gint32 image_id + { + image_type = get_gimp_image_type (img_a->base_type, img_a->transparency); + +- layer_size = img_a->columns * img_a->rows; ++ layer_size = (gsize) img_a->columns * img_a->rows; + pixels = g_malloc (layer_size * base_channels); + for (cidx = 0; cidx < base_channels; ++cidx) + { +- for (i = 0; i < layer_size; ++i) ++ for (gint64 i = 0; i < layer_size; ++i) + { + pixels[(i * base_channels) + cidx] = chn_a[cidx].data[i]; + } +@@ -1700,7 +1699,7 @@ add_merged_image (const gint32 image_id + + /* Draw channels */ + IFDBG(2) g_debug ("Number of channels: %d", extra_channels); +- for (i = 0; i < extra_channels; ++i) ++ for (gint i = 0; i < extra_channels; ++i) + { + /* Alpha channel name */ + alpha_name = NULL; +@@ -1741,8 +1740,8 @@ add_merged_image (const gint32 image_id + } + + cidx = base_channels + i; +- pixels = g_realloc (pixels, chn_a[cidx].columns * chn_a[cidx].rows); +- memcpy (pixels, chn_a[cidx].data, chn_a[cidx].columns * chn_a[cidx].rows); ++ pixels = g_realloc (pixels, (gsize) chn_a[cidx].columns * chn_a[cidx].rows); ++ memcpy (pixels, chn_a[cidx].data, (gsize) chn_a[cidx].columns * chn_a[cidx].rows); + channel_id = gimp_channel_new (image_id, alpha_name, + chn_a[cidx].columns, chn_a[cidx].rows, + alpha_opacity, &alpha_rgb); +@@ -1881,7 +1880,6 @@ read_channel_data (PSDchannel *chann + gchar *src; + gchar *dst; + guint32 readline_len; +- gint i; + + if (bps == 1) + readline_len = ((channel->columns + 7) >> 3); +@@ -1912,7 +1910,7 @@ read_channel_data (PSDchannel *chann + break; + + case PSD_COMP_RLE: +- for (i = 0; i < channel->rows; ++i) ++ for (gint i = 0; i < channel->rows; ++i) + { + src = g_malloc (rle_pack_len[i]); + dst = g_malloc (readline_len); +@@ -1943,17 +1941,17 @@ read_channel_data (PSDchannel *chann + switch (bps) + { + case 16: +- channel->data = (gchar *) g_malloc (channel->rows * channel->columns); ++ channel->data = (gchar *) g_malloc ((gsize) channel->rows * channel->columns); + convert_16_bit (raw_data, channel->data, (channel->rows * channel->columns) << 1); + break; + + case 8: +- channel->data = (gchar *) g_malloc (channel->rows * channel->columns); ++ channel->data = (gchar *) g_malloc ((gsize) channel->rows * channel->columns); + memcpy (channel->data, raw_data, (channel->rows * channel->columns)); + break; + + case 1: +- channel->data = (gchar *) g_malloc (channel->rows * channel->columns); ++ channel->data = (gchar *) g_malloc ((gsize) channel->rows * channel->columns); + convert_1_bit (raw_data, channel->data, channel->rows, channel->columns); + break; + } +@@ -1994,18 +1992,17 @@ convert_1_bit (const gchar *src, + Rows are padded out to a byte boundry. + */ + guint32 row_pos = 0; +- gint i, j; + + IFDBG(3) g_debug ("Start 1 bit conversion"); + +- for (i = 0; i < rows * ((columns + 7) >> 3); ++i) ++ for (gsize i = 0; i < (gsize) rows * ((columns + 7) >> 3); ++i) + { + guchar mask = 0x80; +- for (j = 0; j < 8 && row_pos < columns; ++j) ++ for (gint j = 0; j < 8 && row_pos < columns; ++j) + { + *dst = (*src & mask) ? 0 : 1; + IFDBG(3) g_debug ("byte %d, bit %d, offset %d, src %d, dst %d", +- i , j, row_pos, *src, *dst); ++ (gint) i , j, row_pos, *src, *dst); + dst++; + mask >>= 1; + row_pos++; diff --git a/SOURCES/gimp-CVE-2026-4153.patch b/SOURCES/gimp-CVE-2026-4153.patch new file mode 100644 index 0000000..2598db9 --- /dev/null +++ b/SOURCES/gimp-CVE-2026-4153.patch @@ -0,0 +1,37 @@ +diff -urNp a/plug-ins/common/file-psp.c b/plug-ins/common/file-psp.c +--- a/plug-ins/common/file-psp.c 2026-05-12 13:05:37.736078381 +0200 ++++ b/plug-ins/common/file-psp.c 2026-05-12 13:25:26.657748914 +0200 +@@ -1488,7 +1488,23 @@ read_layer_block (FILE *f, + return -1; + } + +- pixel = g_malloc0 (height * width * bytespp); ++ gint line_width = width * bytespp; ++ ++ if (ia->depth < 8) ++ { ++ gint min_line_width = (((width * ia->depth + 7) / 8) + (ia->depth - 1)) / 4 * 4; ++ ++ /* For small widths, when depth is 1, or 4, the number of bytes ++ * used can be larger than the width * bytespp. Adjust for that. */ ++ if (min_line_width > line_width) ++ { ++ IFDBG(3) g_message ("Adjusting line width from %d to %d\n", ++ line_width, min_line_width); ++ line_width = min_line_width; ++ } ++ } ++ ++ pixel = g_malloc0 (height * line_width); + if (null_layer) + { + pixels = NULL; +@@ -1497,7 +1513,7 @@ read_layer_block (FILE *f, + { + pixels = g_new (guchar *, height); + for (i = 0; i < height; i++) +- pixels[i] = pixel + width * bytespp * i; ++ pixels[i] = pixel + line_width * i; + } + + drawable = gimp_drawable_get (layer_ID); diff --git a/SOURCES/gimp-CVE-2026-4154.patch b/SOURCES/gimp-CVE-2026-4154.patch new file mode 100644 index 0000000..0260b1e --- /dev/null +++ b/SOURCES/gimp-CVE-2026-4154.patch @@ -0,0 +1,70 @@ +diff -urNp a/plug-ins/common/file-xpm.c b/plug-ins/common/file-xpm.c +--- a/plug-ins/common/file-xpm.c 2026-05-12 13:27:01.146402661 +0200 ++++ b/plug-ins/common/file-xpm.c 2026-05-12 13:32:14.273412890 +0200 +@@ -110,7 +110,8 @@ static gint32 load_image (c + static guchar * parse_colors (XpmImage *xpm_image); + static void parse_image (gint32 image_ID, + XpmImage *xpm_image, +- guchar *cmap); ++ guchar *cmap, ++ GError **error); + static gboolean save_image (const gchar *filename, + gint32 image_ID, + gint32 drawable_ID, +@@ -377,6 +378,22 @@ load_image (const gchar *filename, + /* parse out the colors into a cmap */ + cmap = parse_colors (&xpm_image); + ++ if (xpm_image.width > GIMP_MAX_IMAGE_SIZE) ++ { ++ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, ++ _("Unsupported or invalid image width: %d"), ++ xpm_image.width); ++ return NULL; ++ } ++ ++ if (xpm_image.height > GIMP_MAX_IMAGE_SIZE) ++ { ++ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, ++ _("Unsupported or invalid image height: %d"), ++ xpm_image.height); ++ return NULL; ++ } ++ + /* create the new image */ + image_ID = gimp_image_new (xpm_image.width, + xpm_image.height, +@@ -386,7 +403,7 @@ load_image (const gchar *filename, + gimp_image_set_filename (image_ID, filename); + + /* fill it */ +- parse_image (image_ID, &xpm_image, cmap); ++ parse_image (image_ID, &xpm_image, cmap, error); + + /* clean up and exit */ + g_free (cmap); +@@ -463,7 +480,8 @@ parse_colors (XpmImage *xpm_image) + static void + parse_image (gint32 image_ID, + XpmImage *xpm_image, +- guchar *cmap) ++ guchar *cmap, ++ GError **error) + { + gint tile_height; + gint scanlines; +@@ -495,7 +513,13 @@ parse_image (gint32 image_ID, + + tile_height = gimp_tile_height (); + +- buf = g_new (guchar, tile_height * xpm_image->width * 4); ++ buf = g_try_new (guchar, tile_height * xpm_image->width * 4); ++ if (buf == NULL) ++ { ++ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, ++ "%s", _("XPM file invalid")); ++ return; ++ } + + src = xpm_image->data; + for (i = 0; i < xpm_image->height; i+=tile_height) diff --git a/SOURCES/gimp-CVE-2026-4887.patch b/SOURCES/gimp-CVE-2026-4887.patch new file mode 100644 index 0000000..16b07d5 --- /dev/null +++ b/SOURCES/gimp-CVE-2026-4887.patch @@ -0,0 +1,79 @@ +diff -urNp a/plug-ins/common/file-pcx.c b/plug-ins/common/file-pcx.c +--- a/plug-ins/common/file-pcx.c 2026-05-12 13:34:33.676759591 +0200 ++++ b/plug-ins/common/file-pcx.c 2026-05-12 13:43:27.585530991 +0200 +@@ -348,7 +348,7 @@ load_image (const gchar *filename, + FILE *fd; + GimpDrawable *drawable; + GimpPixelRgn pixel_rgn; +- guint16 offset_x, offset_y, bytesperline; ++ guint16 offset_x, offset_y, bytesperline, computed_bytesperline; + gint32 width, height; + gint32 image, layer; + guchar *dest, cmap[768]; +@@ -405,13 +405,28 @@ load_image (const gchar *filename, + fclose (fd); + return -1; + } +- if (bytesperline < ((width * pcx_header.bpp + 7) / 8)) ++ if (pcx_header.bpp != 1 && pcx_header.bpp != 2 && pcx_header.bpp != 4 && ++ pcx_header.bpp != 8) + { +- g_message (_("Invalid number of bytes per line in PCX header")); ++ /* FIXME: After string freeze this should be changed to a more descriptive error. */ ++ g_message (_("Unusual PCX flavour, giving up")); + fclose (fd); + return -1; + } + ++ /* Some legacy images have incorrect values for bytesperline, that are ++ * off by 1. To be able to load these, we will allow a difference of 1 here. ++ * However, that means we need to allocate 1 more byte than officially ++ * required to make sure we don't cause a buffer overrun. ++ * For larger differences we will compute the value of bytesperline. ++ */ ++ computed_bytesperline = (width * pcx_header.bpp + 7) / 8; ++ if (bytesperline + 1 < computed_bytesperline || bytesperline == 0) ++ { ++ g_message (_("Invalid number of bytes per line in PCX header")); ++ bytesperline = (width * pcx_header.bpp + 7) / 8; ++ } ++ + /* Shield against potential buffer overflows in load_*() functions. */ + if (G_MAXSIZE / width / height < 3) + { +@@ -491,7 +506,7 @@ load_8 (FILE *fp, + guint16 bytes) + { + gint row; +- guchar *line = g_new (guchar, bytes); ++ guchar *line = g_new0 (guchar, bytes + 1); + + for (row = 0; row < height; buffer += width, ++row) + { +@@ -511,7 +526,7 @@ load_24 (FILE *fp, + guint16 bytes) + { + gint x, y, c; +- guchar *line = g_new (guchar, bytes); ++ guchar *line = g_new0 (guchar, bytes + 1); + + for (y = 0; y < height; buffer += width * 3, ++y) + { +@@ -537,7 +552,7 @@ load_1 (FILE *fp, + guint16 bytes) + { + gint x, y; +- guchar *line = g_new (guchar, bytes); ++ guchar *line = g_new0 (guchar, bytes + 1); + + for (y = 0; y < height; buffer += width, ++y) + { +@@ -563,7 +578,7 @@ load_4 (FILE *fp, + guint16 bytes) + { + gint x, y, c; +- guchar *line = g_new (guchar, bytes); ++ guchar *line = g_new0 (guchar, bytes + 1); + + for (y = 0; y < height; buffer += width, ++y) + { diff --git a/SPECS/gimp.spec b/SPECS/gimp.spec index 3b01b63..185e98d 100644 --- a/SPECS/gimp.spec +++ b/SPECS/gimp.spec @@ -75,7 +75,7 @@ Summary: GNU Image Manipulation Program Name: gimp Epoch: 2 Version: 2.8.22 -Release: %{?prerelprefix}26%{dotprerel}%{dotgitrev}%{?dist}.5 +Release: %{?prerelprefix}26%{dotprerel}%{dotgitrev}%{?dist}.6 # Compute some version related macros. # Ugly, need to get quoting percent signs straight. @@ -226,7 +226,10 @@ Patch22: gimp-3.0.4-CVE-2026-0797.patch Patch23: gimp-3.0.4-CVE-2026-2044.patch Patch24: gimp-3.0.4-CVE-2026-2045.patch Patch25: gimp-3.0.4-CVE-2026-2048.patch - +Patch26: gimp-CVE-2026-4150.patch +Patch27: gimp-CVE-2026-4153.patch +Patch28: gimp-CVE-2026-4154.patch +Patch29: gimp-CVE-2026-4887.patch # use external help browser directly if help browser plug-in is not built Patch100: gimp-2.8.6-external-help-browser.patch @@ -336,7 +339,10 @@ EOF %patch23 -p1 -b .CVE-2026-2044 %patch24 -p1 -b .CVE-2026-2045 %patch25 -p1 -b .CVE-2026-2048 - +%patch26 -p1 -b .CVE-2026-4150 +%patch27 -p1 -b .CVE-2026-4153 +%patch28 -p1 -b .CVE-2026-4154 +%patch29 -p1 -b .CVE-2026-4887 %if ! %{with helpbrowser} %patch100 -p1 -b .external-help-browser %endif @@ -675,6 +681,12 @@ make check %endif %changelog +* Tue May 12 2026 Josef Ridky - 2:2.8.22-26.6 +- fix CVE-2026-4150 +- fix CVE-2026-4153 +- fix CVE-2026-4154 +- fix CVE-2026-4887 + * Thu Mar 12 2026 Josef Ridky - 2:2.8.22-26.5 - fix CVE-2026-0797 - fix CVE-2026-2044