diff -urNp a/plug-ins/common/file-tga.c b/plug-ins/common/file-tga.c --- a/plug-ins/common/file-tga.c 2025-06-14 14:36:28.298535906 +0200 +++ b/plug-ins/common/file-tga.c 2025-06-14 14:50:52.545808264 +0200 @@ -555,7 +555,7 @@ load_image (const gchar *filename, 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_filename_to_utf8 (filename), @@ -870,32 +870,46 @@ apply_colormap (guchar *dest, guint width, const guchar *cmap, gboolean alpha, - guint16 index) + guint16 colorMapIndex, + guint16 colorMapLength) { guint x; + gint errcnt = 0; - 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]; + guchar entryIndex = src[x] - colorMapIndex; - src++; - } + if (src[x] < colorMapIndex || entryIndex >= colorMapLength) { + /* 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; + } + + 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]; + } } } @@ -951,7 +965,7 @@ read_line (FILE *fp, gboolean has_alpha = (info->alphaBits > 0); apply_colormap (row, buffer, info->width, convert_cmap, has_alpha, - info->colorMapIndex); + info->colorMapIndex, info->colorMapLength); } else if (info->imageType == TGA_TYPE_MAPPED) { @@ -961,7 +975,7 @@ read_line (FILE *fp, } else { - memcpy (row, buffer, info->width * drawable->bpp); + memcpy (row, buffer, info->width * info->bytes); } } @@ -993,9 +1007,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); @@ -1007,13 +1021,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;