update version to 3.0.6

Signed-off-by: Toshaan Bharvani <toshaan@powerel.org>
master
Toshaan Bharvani 2025-11-08 16:07:08 +01:00
parent 707db6f985
commit 3d51222379
11 changed files with 1188 additions and 532 deletions

View File

@ -0,0 +1,98 @@
Built out of the following commits from release 2.10.36:
- 7db71cd0b6e36c454aa0d2d3efeec7e636db4dbc
- e92f279c97282a2b20dca0d923db7465f2057703
- 9dda8139e4d07e3a273436eda993fef32555edbe

Applied onto worktree starting from top to bottom.
---
plug-ins/file-dds/ddsread.c | 39 +++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)

diff --git a/plug-ins/file-dds/ddsread.c b/plug-ins/file-dds/ddsread.c
index 72102d0e1c..ba5b712edd 100644
--- a/plug-ins/file-dds/ddsread.c
+++ b/plug-ins/file-dds/ddsread.c
@@ -124,6 +124,7 @@ read_dds (GFile *file,
guint l = 0;
guchar *pixels;
FILE *fp;
+ gsize file_size;
dds_header_t hdr;
dds_header_dx10_t dx10hdr;
dds_load_info_t d;
@@ -157,6 +158,10 @@ read_dds (GFile *file,
return GIMP_PDB_EXECUTION_ERROR;
}
+ fseek (fp, 0L, SEEK_END);
+ file_size = ftell (fp);
+ fseek (fp, 0, SEEK_SET);
+
gimp_progress_init_printf ("Loading %s:", gimp_file_get_utf8_name (file));
/* read header */
@@ -317,6 +322,16 @@ read_dds (GFile *file,
precision = GIMP_PRECISION_U8_NON_LINEAR;
}
+ /* verify header information is accurate */
+ if (hdr.depth < 1 ||
+ (hdr.pitch_or_linsize > (file_size - sizeof (hdr))) ||
+ (((guint64) hdr.height * hdr.width * hdr.depth) > (file_size - sizeof (hdr))))
+ {
+ fclose (fp);
+ g_message ("Invalid or corrupted DDS header\n");
+ return GIMP_PDB_EXECUTION_ERROR;
+ }
+
image = gimp_image_new_with_precision (hdr.width, hdr.height, type, precision);
if (! image)
@@ -985,6 +1000,14 @@ load_layer (FILE *fp,
guint size = hdr->pitch_or_linsize >> (2 * level);
guint layerw;
gint format = DDS_COMPRESS_NONE;
+ gsize file_size;
+ gsize current_position;
+
+ current_position = ftell (fp);
+ fseek (fp, 0L, SEEK_END);
+ file_size = ftell (fp);
+ fseek (fp, 0, SEEK_SET);
+ fseek (fp, current_position, SEEK_SET);
if (width < 1) width = 1;
if (height < 1) height = 1;
@@ -1082,6 +1105,13 @@ load_layer (FILE *fp,
size *= 16;
}
+ if (size > (file_size - current_position) ||
+ size > hdr->pitch_or_linsize)
+ {
+ g_message ("Requested data exceeds size of file.\n");
+ return 0;
+ }
+
if ((hdr->flags & DDSD_LINEARSIZE) &&
!fread (buf, size, 1, fp))
{
@@ -1121,6 +1151,15 @@ load_layer (FILE *fp,
gimp_progress_update ((double) y / (double) hdr->height);
}
+ current_position = ftell (fp);
+ if ((hdr->flags & DDSD_PITCH) &&
+ ((width * d->bpp) > (file_size - current_position) ||
+ (width * d->bpp) > hdr->pitch_or_linsize))
+ {
+ g_message ("Requested data exceeds size of file.\n");
+ return 0;
+ }
+
if ((hdr->flags & DDSD_PITCH) &&
! fread (buf, width * d->bpp, 1, fp))
{
--
2.43.0

View File

@ -0,0 +1,20 @@
O-Commit: 865cc56894dcb6e1c664a55e4b4010ebf6919e10
---
plug-ins/file-psd/psd-util.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/plug-ins/file-psd/psd-util.c b/plug-ins/file-psd/psd-util.c
index 761865e7af..545bd32f7c 100644
--- a/plug-ins/file-psd/psd-util.c
+++ b/plug-ins/file-psd/psd-util.c
@@ -583,6 +583,7 @@ decode_packbits (const gchar *src,
{
IFDBG(2) g_debug ("Overrun in packbits replicate of %d chars", n - unpack_left);
error_code = 2;
+ break;
}
memset (dst, *src, n);
src++;
--
2.43.0

View File

@ -0,0 +1,31 @@
O-Commit: 9c9521e99dd24a73fe7701bf5bde6dbbd26c4862
---
plug-ins/common/file-psp.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/plug-ins/common/file-psp.c b/plug-ins/common/file-psp.c
index f891ca1856..6944ad4072 100644
--- a/plug-ins/common/file-psp.c
+++ b/plug-ins/common/file-psp.c
@@ -1278,8 +1278,17 @@ read_color_block (FILE *f,
}
color_palette_entries = GUINT32_FROM_LE (entry_count);
+ /* TODO: GIMP currently only supports a maximum of 256 colors
+ * in an indexed image. If this changes, we can change this check */
+ if (color_palette_entries > 256)
+ {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ _("Error: Unsupported palette size"));
+ return -1;
+ }
+
/* psp color palette entries are stored as RGBA so 4 bytes per entry
- where the fourth bytes is always zero */
+ * where the fourth bytes is always zero */
pal_size = color_palette_entries * 4;
color_palette = g_malloc (pal_size);
if (fread (color_palette, pal_size, 1, f) < 1)
--
2.43.0

View File

@ -0,0 +1,21 @@
O-Commit: d52d32cb82905e4ee58d249dcde9e8d47f2b915d
---
plug-ins/common/file-psp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/plug-ins/common/file-psp.c b/plug-ins/common/file-psp.c
index 6944ad4072..d1156d4732 100644
--- a/plug-ins/common/file-psp.c
+++ b/plug-ins/common/file-psp.c
@@ -1657,7 +1657,7 @@ read_channel_data (FILE *f,
else
endq = q + line_width * height;
- buf = g_malloc (127);
+ buf = g_malloc (128);
while (q < endq)
{
fread (&runcount, 1, 1, f);
--
2.43.0

View File

@ -0,0 +1,25 @@
diff -up gimp-2.99.18/etc/gimprc.in.cm-system-monitor-profile-by-default gimp-2.99.18/etc/gimprc.in
--- gimp-2.99.18/etc/gimprc.in.cm-system-monitor-profile-by-default 2024-02-17 18:01:20.000000000 +0100
+++ gimp-2.99.18/etc/gimprc.in 2024-05-07 14:39:06.468575598 +0200
@@ -316,9 +316,9 @@
# Defines the color management behavior. This is a parameter list.
#
-# (color-management
+(color-management
# (mode display)
-# (display-profile-from-gdk no)
+ (display-profile-from-gdk no)
# (display-rendering-intent relative-colorimetric)
# (display-use-black-point-compensation yes)
# (display-optimize yes)
@@ -326,7 +326,8 @@
# (simulation-use-black-point-compensation no)
# (simulation-optimize yes)
# (simulation-gamut-check no)
-# (out-of-gamut-color (color-rgb 1 0 1)))
+# (out-of-gamut-color (color-rgb 1 0 1))
+)
# Keep a permanent record of all opened and saved files in the Recent
# Documents list. Possible values are yes and no.

View File

@ -0,0 +1,12 @@
diff -up gimp-2.99.18/etc/gimprc.in.external-help-browser gimp-2.99.18/etc/gimprc.in
--- gimp-2.99.18/etc/gimprc.in.external-help-browser 2024-05-07 14:41:40.660506520 +0200
+++ gimp-2.99.18/etc/gimprc.in 2024-05-07 14:46:04.028680986 +0200
@@ -828,7 +828,7 @@
# Sets the browser used by the help system. Possible values are gimp and
# web-browser.
#
-# (help-browser gimp)
+(help-browser web-browser)
# The maximum number of actions saved in history. This is an integer value.
#

View File

@ -0,0 +1,12 @@
diff -up gimp-2.99.18/etc/gimprc.in.no-phone-home-default gimp-2.99.18/etc/gimprc.in
--- gimp-2.99.18/etc/gimprc.in.no-phone-home-default 2024-05-07 14:40:02.746185394 +0200
+++ gimp-2.99.18/etc/gimprc.in 2024-05-07 14:40:49.353862228 +0200
@@ -399,7 +399,7 @@
# Check for availability of GIMP updates through background internet queries.
# Possible values are yes and no.
#
-# (check-updates yes)
+(check-updates no)
# Timestamp of the last update check. This is an integer value.
#

View File

@ -0,0 +1,159 @@
diff --git a/plug-ins/common/file-tga.c b/plug-ins/common/file-tga.c
index f6f24a13194..c0d7ad94c20 100644
--- a/plug-ins/common/file-tga.c
+++ b/plug-ins/common/file-tga.c
@@ -982,9 +982,9 @@ ReadImage (FILE *fp,
cmap_bytes = (info->colorMapSize + 7 ) / 8;
tga_cmap = g_new (guchar, info->colorMapLength * cmap_bytes);
- if (info->colorMapSize > 24)
+ if (info->colorMapSize > 24 || info->alphaBits > 0)
{
- /* indexed + full alpha => promoted to RGBA */
+ /* indexed + full alpha, or alpha exists => promoted to RGBA */
itype = GIMP_RGB;
dtype = GIMP_RGBA_IMAGE;
convert_cmap = g_new (guchar, info->colorMapLength * 4);
@@ -996,13 +996,6 @@ ReadImage (FILE *fp,
dtype = GIMP_RGB_IMAGE;
convert_cmap = g_new (guchar, info->colorMapLength * 3);
}
- else if (info->alphaBits > 0)
- {
- /* if alpha exists here, promote to RGB */
- itype = GIMP_RGB;
- dtype = GIMP_RGBA_IMAGE;
- convert_cmap = g_new (guchar, info->colorMapLength * 4);
- }
else
{
itype = GIMP_INDEXED;
---
diff --git a/plug-ins/common/file-tga.c b/plug-ins/common/file-tga.c
index c0d7ad94c20..433410ff471 100644
--- a/plug-ins/common/file-tga.c
+++ b/plug-ins/common/file-tga.c
@@ -539,7 +539,7 @@ load_image (GFile *file,
switch (info.imageType)
{
case TGA_TYPE_MAPPED:
- if (info.bpp != 8)
+ if (info.bpp != 8 || !info.colorMapLength)
{
g_message ("Unhandled sub-format in '%s' (type = %u, bpp = %u)",
gimp_file_get_utf8_name (file),
@@ -862,32 +862,31 @@ apply_colormap (guchar *dest,
guint width,
const guchar *cmap,
gboolean alpha,
- guint16 index)
+ guint16 colorMapIndex,
+ guint16 colorMapLength)
{
guint x;
- if (alpha)
- {
- for (x = 0; x < width; x++)
- {
- *(dest++) = cmap[(*src - index) * 4];
- *(dest++) = cmap[(*src - index) * 4 + 1];
- *(dest++) = cmap[(*src - index) * 4 + 2];
- *(dest++) = cmap[(*src - index) * 4 + 3];
-
- src++;
- }
- }
- else
+ for (x = 0; x < width; x++)
{
- for (x = 0; x < width; x++)
- {
- *(dest++) = cmap[(*src - index) * 3];
- *(dest++) = cmap[(*src - index) * 3 + 1];
- *(dest++) = cmap[(*src - index) * 3 + 2];
-
- src++;
- }
+ guchar entryIndex = src[x] - colorMapIndex;
+
+ if (src[x] < colorMapIndex || entryIndex >= colorMapLength) {
+ g_message ("Unsupported colormap entry: %u",
+ src[x]);
+ entryIndex = 0;
+ }
+
+ if (alpha) {
+ *(dest++) = cmap[entryIndex * 4];
+ *(dest++) = cmap[entryIndex * 4 + 1];
+ *(dest++) = cmap[entryIndex * 4 + 2];
+ *(dest++) = cmap[entryIndex * 4 + 3];
+ } else {
+ *(dest++) = cmap[entryIndex * 3];
+ *(dest++) = cmap[entryIndex * 3 + 1];
+ *(dest++) = cmap[entryIndex * 3 + 2];
+ }
}
}
@@ -943,7 +942,7 @@ read_line (FILE *fp,
gboolean has_alpha = (info->alphaBits > 0);
apply_colormap (row, buf, info->width, convert_cmap, has_alpha,
- info->colorMapIndex);
+ info->colorMapIndex, info->colorMapLength);
}
else if (info->imageType == TGA_TYPE_MAPPED)
{
---
diff --git a/plug-ins/common/file-tga.c b/plug-ins/common/file-tga.c
index 433410ff471..a171a264772 100644
--- a/plug-ins/common/file-tga.c
+++ b/plug-ins/common/file-tga.c
@@ -952,7 +952,7 @@ read_line (FILE *fp,
}
else
{
- memcpy (row, buf, info->width * bpp);
+ memcpy (row, buf, info->width * info->bytes);
}
}
---
diff --git a/plug-ins/common/file-tga.c b/plug-ins/common/file-tga.c
index a171a264772..abecde86857 100644
--- a/plug-ins/common/file-tga.c
+++ b/plug-ins/common/file-tga.c
@@ -866,14 +866,29 @@ apply_colormap (guchar *dest,
guint16 colorMapLength)
{
guint x;
+ gint errcnt = 0;
for (x = 0; x < width; x++)
{
guchar entryIndex = src[x] - colorMapIndex;
if (src[x] < colorMapIndex || entryIndex >= colorMapLength) {
- g_message ("Unsupported colormap entry: %u",
- src[x]);
+ /* On Windows the error console can run out of resources when
+ * producing a huge amount of messages. This can happen when using
+ * fuzzed test images. This causes unresponsiveness at first and
+ * finally crashes GIMP. Eventually this needs to be fixed at the
+ * source, but for now let's limit the error messages to 10
+ * per line (this function is called once per read_line). */
+ if (errcnt < 10)
+ {
+ g_message ("Unsupported colormap entry: %u",
+ src[x]);
+ }
+ else if (errcnt == 10)
+ {
+ g_message ("Too many colormap errors. Image may be corrupt.");
+ }
+ errcnt++;
entryIndex = 0;
}
---

View File

@ -0,0 +1,93 @@
diff -urNp a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
--- a/app/xcf/xcf-load.c 2025-06-14 13:08:43.443446885 +0200
+++ b/app/xcf/xcf-load.c 2025-06-14 13:22:09.771911460 +0200
@@ -102,7 +102,8 @@ static gboolean xcf_check_layer_p
gboolean *is_text_layer);
static gboolean xcf_load_channel_props (XcfInfo *info,
GimpImage *image,
- GimpChannel **channel);
+ GimpChannel **channel,
+ gboolean is_mask);
static gboolean xcf_load_prop (XcfInfo *info,
PropType *prop_type,
guint32 *prop_size);
@@ -1213,6 +1214,14 @@ xcf_load_layer_props (XcfInfo *info,
case PROP_ACTIVE_LAYER:
info->selected_layers = g_list_prepend (info->selected_layers, *layer);
+ {
+ if (g_list_index (info->selected_layers, *layer) < 0)
+ info->selected_layers = g_list_prepend (info->selected_layers, *layer);
+ else
+ gimp_message_literal (info->gimp, G_OBJECT (info->progress),
+ GIMP_MESSAGE_WARNING,
+ "Invalid duplicate selected layer detected");
+ }
break;
case PROP_FLOATING_SELECTION:
@@ -1663,7 +1672,8 @@ xcf_check_layer_props (XcfInfo *info,
static gboolean
xcf_load_channel_props (XcfInfo *info,
GimpImage *image,
- GimpChannel **channel)
+ GimpChannel **channel,
+ gboolean is_mask)
{
PropType prop_type;
guint32 prop_size;
@@ -1686,6 +1696,36 @@ xcf_load_channel_props (XcfInfo *in
{
GimpChannel *mask;
+ if (is_mask)
+ {
+ /* PROP_SELECTION is not valid for masks, and we have to avoid
+ * overwriting the channel.
+ */
+ continue;
+ }
+
+ if (*channel == gimp_image_get_mask (image))
+ {
+ /* PROP_SELECTION was already seen once for this
+ * channel. Let's silently ignore the second identical
+ * property to avoid a double free.
+ */
+ continue;
+ }
+ else if (gimp_image_get_mask (image) != NULL &&
+ ! gimp_channel_is_empty (gimp_image_get_mask (image)))
+ {
+ /* This would happen when PROP_SELECTION was already set
+ * on a previous channel. This is a minor case of data
+ * loss (we don't know which selection was the right one
+ * and we drop the non-first ones), and also means it's
+ * a broken XCF, though it's not a major bug either. So
+ * let's go with a stderr print.
+ */
+ g_printerr ("PROP_SELECTION property was set on 2 channels (skipping)\n");
+ continue;
+ }
+
/* We're going to delete *channel, Don't leave its pointer
* in @info. See bug #767873.
*/
@@ -2155,7 +2195,7 @@ xcf_load_channel (XcfInfo *info,
return NULL;
/* read in the channel properties */
- if (! xcf_load_channel_props (info, image, &channel))
+ if (! xcf_load_channel_props (info, image, &channel, FALSE))
goto error;
xcf_progress_update (info);
@@ -2228,7 +2268,7 @@ xcf_load_layer_mask (XcfInfo *info,
/* read in the layer_mask properties */
channel = GIMP_CHANNEL (layer_mask);
- if (! xcf_load_channel_props (info, image, &channel))
+ if (! xcf_load_channel_props (info, image, &channel, TRUE))
goto error;
xcf_progress_update (info);

View File

@ -0,0 +1,18 @@
diff --git a/plug-ins/file-ico/ico-load.c b/plug-ins/file-ico/ico-load.c
index 9a222998bc1..818cf23cd31 100644
--- a/plug-ins/file-ico/ico-load.c
+++ b/plug-ins/file-ico/ico-load.c
@@ -299,7 +299,11 @@ ico_read_png (FILE *fp,
png_read_info (png_ptr, info);
png_get_IHDR (png_ptr, info, &w, &h, &bit_depth, &color_type,
NULL, NULL, NULL);
- if (w*h*4 > maxsize)
+ /* Check for overflow */
+ if ((w * h * 4) < w ||
+ (w * h * 4) < h ||
+ (w * h * 4) < (w * h) ||
+ (w * h * 4) > maxsize)
{
png_destroy_read_struct (&png_ptr, &info, NULL);
return FALSE;
---

File diff suppressed because it is too large Load Diff