File gimp-CVE-2026-4150.patch of Package gimp
From 00afdabdadeb5457fd897878b1e5aebc3780af10 Mon Sep 17 00:00:00 2001
From: Jacob Boerema <jgboerema@gmail.com>
Date: Fri, 6 Mar 2026 10:01:09 -0500
Subject: [PATCH] plug-ins: fix #15967 integer overflow in psd-load
Reported as ZDI-CAN-28807
With large row and column sizes 32-bit int values are not large
enough to hold the product and thus can cause overflow.
While we are at it, we not only fix the location from the report, but
also other occurrences that could overflow.
- We change certain variables to gsize to make sure they can hold a
64-bit value.
- Other intermediate results are promoted to (gsize) to make sure that
the product is computed as gsize.
- Move some i,j variables to the loops where they are used.
(cherry picked from commit 7e1241f75147bf6e705a31c81e4d5efab1df1668)
---
plug-ins/file-psd/psd-load.c | 44 ++++++++++++++++--------------------
1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/plug-ins/file-psd/psd-load.c b/plug-ins/file-psd/psd-load.c
index 0ec888c2ec9..676f3da9b41 100644
--- a/plug-ins/file-psd/psd-load.c
+++ b/plug-ins/file-psd/psd-load.c
@@ -2813,14 +2813,13 @@ add_merged_image (GimpImage *image,
guint16 bps;
guint32 *rle_pack_len[MAX_CHANNELS];
guint32 alpha_id;
- gint32 layer_size;
+ gsize layer_size;
GimpLayer *layer = NULL;
GimpChannel *channel = NULL;
gint16 alpha_opacity;
gint cidx; /* Channel index */
gint rowi; /* Row index */
gint offset;
- gint i;
gboolean alpha_visible;
gboolean alpha_channel = FALSE;
GeglBuffer *buffer;
@@ -2975,11 +2974,11 @@ add_merged_image (GimpImage *image,
image_type = get_gimp_image_type (img_a->base_type,
img_a->transparency || alpha_channel);
- layer_size = img_a->columns * img_a->rows;
+ layer_size = (gsize) img_a->columns * img_a->rows;
pixels = g_malloc (layer_size * base_channels * bps);
for (cidx = 0; cidx < base_channels; ++cidx)
{
- for (i = 0; i < layer_size; ++i)
+ for (gint64 i = 0; i < layer_size; ++i)
{
memcpy (&pixels[((i * base_channels) + cidx) * bps],
&chn_a[cidx].data[i * bps], bps);
@@ -3051,7 +3050,7 @@ add_merged_image (GimpImage *image,
{
gfloat *data = iter->items[0].data;
- for (i = 0; i < iter->length; i++)
+ for (gint i = 0; i < iter->length; i++)
{
gint c;
@@ -3103,7 +3102,7 @@ add_merged_image (GimpImage *image,
/* 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;
@@ -3144,8 +3143,8 @@ add_merged_image (GimpImage *image,
}
cidx = base_channels + i;
- pixels = g_realloc (pixels, chn_a[cidx].columns * chn_a[cidx].rows * bps);
- memcpy (pixels, chn_a[cidx].data, chn_a[cidx].columns * chn_a[cidx].rows * bps);
+ pixels = g_realloc (pixels, (gsize) chn_a[cidx].columns * chn_a[cidx].rows * bps);
+ memcpy (pixels, chn_a[cidx].data, (gsize) chn_a[cidx].columns * chn_a[cidx].rows * bps);
channel = gimp_channel_new (image, alpha_name,
chn_a[cidx].columns, chn_a[cidx].rows,
alpha_opacity, alpha_rgb);
@@ -3332,7 +3331,6 @@ read_channel_data (PSDchannel *channel,
gchar *raw_data = NULL;
gchar *src;
guint32 readline_len;
- gint i, j;
if (bps == 1)
readline_len = ((channel->columns + 7) / 8);
@@ -3364,7 +3362,7 @@ read_channel_data (PSDchannel *channel,
break;
case PSD_COMP_RLE:
- for (i = 0; i < channel->rows; ++i)
+ for (gint i = 0; i < channel->rows; ++i)
{
src = gegl_scratch_alloc (rle_pack_len[i]);
/* FIXME check for over-run
@@ -3433,12 +3431,11 @@ read_channel_data (PSDchannel *channel,
case 32:
{
guint32 *data;
- guint64 pos;
if (compression == PSD_COMP_ZIP_PRED)
{
IFDBG(3) g_debug ("Converting 32 bit predictor data");
- channel->data = (gchar *) g_malloc0 (channel->rows * channel->columns * 4);
+ channel->data = (gchar *) g_malloc0 ((gsize) channel->rows * channel->columns * 4);
decode_32_bit_predictor (raw_data, channel->data,
channel->rows, channel->columns);
}
@@ -3450,7 +3447,7 @@ read_channel_data (PSDchannel *channel,
}
data = (guint32*) channel->data;
- for (pos = 0; pos < channel->rows * channel->columns; ++pos)
+ for (gsize pos = 0; pos < (gsize) channel->rows * channel->columns; ++pos)
data[pos] = GUINT32_FROM_BE (data[pos]);
break;
@@ -3463,14 +3460,14 @@ read_channel_data (PSDchannel *channel,
channel->data = raw_data;
raw_data = NULL;
- for (i = 0; i < channel->rows * channel->columns; ++i)
+ for (gsize i = 0; i < (gsize) channel->rows * channel->columns; ++i)
data[i] = GUINT16_FROM_BE (data[i]);
if (compression == PSD_COMP_ZIP_PRED)
{
IFDBG(3) g_debug ("Converting 16 bit predictor data");
- for (i = 0; i < channel->rows; ++i)
- for (j = 1; j < channel->columns; ++j)
+ for (gsize i = 0; i < channel->rows; ++i)
+ for (gsize j = 1; j < channel->columns; ++j)
data[i * channel->columns + j] += data[i * channel->columns + j - 1];
}
break;
@@ -3483,14 +3480,14 @@ read_channel_data (PSDchannel *channel,
if (compression == PSD_COMP_ZIP_PRED)
{
IFDBG(3) g_debug ("Converting 8 bit predictor data");
- for (i = 0; i < channel->rows; ++i)
- for (j = 1; j < channel->columns; ++j)
+ for (gsize i = 0; i < channel->rows; ++i)
+ for (gsize j = 1; j < channel->columns; ++j)
channel->data[i * channel->columns + j] += channel->data[i * channel->columns + j - 1];
}
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;
@@ -3540,7 +3537,7 @@ decode_32_bit_predictor (gchar *src,
/* restore byte order */
dstpos = 0;
- for (row = 0; row < rows * rowsize; row += rowsize)
+ for (row = 0; row < (gsize) rows * rowsize; row += rowsize)
{
guint64 offset;
@@ -3567,18 +3564,17 @@ convert_1_bit (const gchar *src,
Rows are padded out to a byte boundary.
*/
guint32 row_pos = 0;
- gint i, j;
IFDBG(3) g_debug ("Start 1 bit conversion");
- for (i = 0; i < rows * ((columns + 7) / 8); ++i)
+ for (gsize i = 0; i < (gsize) rows * ((columns + 7) / 8); ++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(4) 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++;
--
GitLab