gimp/SOURCES/gimp-CVE-2026-66759.patch
2026-08-06 03:11:47 -04:00

167 lines
6.3 KiB
Diff

From f484e007afd332f3f1bde204a92cb87a54cbaa3c Mon Sep 17 00:00:00 2001
From: Alx Sa <cmyk.student@gmail.com>
Date: Tue, 7 Jul 2026 15:54:40 +0000
Subject: [PATCH 1/2] plug-ins: Mitigate OOB write on ICNS mask data
As reported by Tristan, it is possible to create an ICNS
icon with mask data smaller than the icon size. In this case,
our current code could potentially go out of bounds when writing
from file. This patch adds a check to stop executing the code if
we reach the end of the mask data in the file.
---
plug-ins/file-icns/file-icns-load.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/plug-ins/file-icns/file-icns-load.c b/plug-ins/file-icns/file-icns-load.c
index cd76c710fd..18cd007a39 100644
--- a/plug-ins/file-icns/file-icns-load.c
+++ b/plug-ins/file-icns/file-icns-load.c
@@ -341,7 +341,7 @@ icns_decompress (guchar *dest,
{
if (out > max)
{
- g_message ("Corrupt icon? compressed run overflows output size.");
+ g_message ("Corrupt icon: compressed run overflows output size.");
return FALSE;
}
dest[out++ * 4 + channel] = val;
@@ -387,10 +387,19 @@ icns_decompress (guchar *dest,
else if (mask)
{
gchar typestring[5];
- fourcc_get_string (mask->type, typestring);
+ fourcc_get_string (mask->type, typestring);
for (out = 0; out < max; out++)
- dest[out * 4 + 3] = mask->data[mask->cursor++];
+ {
+ if (mask->cursor >= mask->size)
+ {
+ g_message ("Corrupt icon mask: uncompressed run overflows input "
+ "size.");
+ return FALSE;
+ }
+
+ dest[out * 4 + 3] = mask->data[mask->cursor++];
+ }
}
return TRUE;
}
From 49092ca0ffacae3ae97caba136139f9734c91ac9 Mon Sep 17 00:00:00 2001
From: Alx Sa <cmyk.student@gmail.com>
Date: Tue, 7 Jul 2026 16:49:21 +0000
Subject: [PATCH 2/2] plug-ins: Correct mask loading in ICNS
In some instances, we did checks on and pulled bytes
from the icon data instead of the mask data.
This patch corrects the issue.
In addition, in the unlikely event that GIMP is packaged
on a 32-bit system, we now also guard against an overflow
when allocating IcnsResources.
---
plug-ins/file-icns/file-icns-load.c | 42 ++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 10 deletions(-)
diff --git a/plug-ins/file-icns/file-icns-load.c b/plug-ins/file-icns/file-icns-load.c
index 18cd007a39..fcefefa8f8 100644
--- a/plug-ins/file-icns/file-icns-load.c
+++ b/plug-ins/file-icns/file-icns-load.c
@@ -82,14 +82,17 @@ resource_load (FILE *file)
{
gchar type[5];
guint32 size;
+ gsize allocation;
strncpy (type, header.type, 4);
type[4] = '\0';
size = GUINT32_FROM_BE (header.size);
- if (! strncmp (header.type, "icns", 4) && size > sizeof (IcnsResourceHeader))
+ if (! strncmp (header.type, "icns", 4) &&
+ size > sizeof (IcnsResourceHeader) &&
+ g_size_checked_add (&allocation, sizeof (IcnsResource), size))
{
- res = (IcnsResource *) g_new (guchar, sizeof (IcnsResource) + size);
+ res = (IcnsResource *) g_new (guchar, allocation);
strncpy (res->type, header.type, 4);
res->type[4] = '\0';
res->size = size;
@@ -235,8 +238,8 @@ icns_slurp (guchar *dest,
if (out % 8 == 0)
bucket = icns->data[icns->cursor++];
- bit = (bucket & 0x80) ? 0 : 255;
- bucket = bucket << 1;
+ bit = (bucket & 0x80) ? 0 : 255;
+ bucket = bucket << 1;
dest[out * 4] = bit;
dest[out * 4 + 1] = bit;
dest[out * 4 + 2] = bit;
@@ -250,8 +253,8 @@ icns_slurp (guchar *dest,
if (out % 2 == 0)
bucket = icns->data[icns->cursor++];
- index = 3 * (bucket & 0xf0) >> 4;
- bucket = bucket << 4;
+ index = 3 * (bucket & 0xf0) >> 4;
+ bucket = bucket << 4;
dest[out * 4] = icns_colormap_4[index];
dest[out * 4 + 1] = icns_colormap_4[index + 1];
dest[out * 4 + 2] = icns_colormap_4[index + 2];
@@ -260,7 +263,13 @@ icns_slurp (guchar *dest,
case 8:
for (out = 0; out < max; out++)
{
- index = 3 * icns->data[icns->cursor++];
+ if (icns->cursor >= icns->size)
+ {
+ g_message ("Invalid or corrupt icns resource file.");
+ return;
+ }
+
+ index = 3 * icns->data[icns->cursor++];
dest[out * 4] = icns_colormap_8[index];
dest[out * 4 + 1] = icns_colormap_8[index + 1];
dest[out * 4 + 2] = icns_colormap_8[index + 2];
@@ -270,13 +279,26 @@ icns_slurp (guchar *dest,
case 32:
for (out = 0; out < max; out++)
{
+ if (icns->size < 4 || icns->cursor > icns->size - 4)
+ {
+ g_message ("Invalid or corrupt icns resource file.");
+ return;
+ }
+
dest[out * 4] = icns->data[icns->cursor++];
dest[out * 4 + 1] = icns->data[icns->cursor++];
dest[out * 4 + 2] = icns->data[icns->cursor++];
/* Throw away alpha, use the mask */
icns->cursor++;
+
+ if (mask && mask->cursor >= mask->size)
+ {
+ g_message ("Invalid or corrupt icns resource file.");
+ return;
+ }
+
if (mask)
- dest[out * 4 + 3] = icns->data[mask->cursor++];
+ dest[out * 4 + 3] = mask->data[mask->cursor++];
else
dest[out * 4 + 3] = 255;
}
@@ -292,8 +314,8 @@ icns_slurp (guchar *dest,
if (out % 8 == 0)
bucket = mask->data[mask->cursor++];
- bit = (bucket & 0x80) ? 255 : 0;
- bucket = bucket << 1;
+ bit = (bucket & 0x80) ? 255 : 0;
+ bucket = bucket << 1;
dest[out * 4 + 3] = bit;
}
}