167 lines
6.3 KiB
Diff
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;
|
|
}
|
|
}
|