File gimp-CVE-2023-44441.patch of Package gimp
--- gimp-2.10.30.orig/plug-ins/file-dds/ddsread.c 2023-11-17 19:46:12.782841827 +0530
+++ gimp-2.10.30/plug-ins/file-dds/ddsread.c 2023-11-28 15:42:07.554295500 +0530
@@ -109,6 +109,7 @@ read_dds (gchar *filename,
guchar *pixels;
gchar *tmp;
FILE *fp;
+ gsize file_size;
dds_header_t hdr;
dds_header_dx10_t dx10hdr;
dds_load_info_t d;
@@ -116,6 +117,7 @@ read_dds (gchar *filename,
GimpImageBaseType type;
GimpPrecision precision;
int i, j;
+ guint computed_pitch_or_linsize;
if (interactive_dds)
{
@@ -130,6 +132,10 @@ read_dds (gchar *filename,
return GIMP_PDB_EXECUTION_ERROR;
}
+ fseek (fp, 0L, SEEK_END);
+ file_size = ftell (fp);
+ fseek (fp, 0, SEEK_SET);
+
if (strrchr (filename, '/'))
tmp = g_strdup_printf ("Loading %s:", strrchr (filename, '/') + 1);
else
@@ -162,29 +168,32 @@ read_dds (gchar *filename,
}
/* a lot of DDS images out there don't have this for some reason -_- */
- if (hdr.pitch_or_linsize == 0)
- {
if (hdr.pixelfmt.flags & DDPF_FOURCC) /* assume linear size */
{
- hdr.pitch_or_linsize = ((hdr.width + 3) >> 2) * ((hdr.height + 3) >> 2);
- switch (GETL32(hdr.pixelfmt.fourcc))
- {
+ computed_pitch_or_linsize = ((hdr.width + 3) >> 2) * ((hdr.height + 3) >> 2);
+ switch (GETL32 (hdr.pixelfmt.fourcc))
+ {
case FOURCC ('D','X','T','1'):
case FOURCC ('A','T','I','1'):
case FOURCC ('B','C','4','U'):
case FOURCC ('B','C','4','S'):
- hdr.pitch_or_linsize *= 8;
- break;
+ computed_pitch_or_linsize *= 8;
+ break;
default:
- hdr.pitch_or_linsize *= 16;
- break;
- }
+ computed_pitch_or_linsize *= 16;
+ break;
+ }
}
else /* assume pitch */
{
- hdr.pitch_or_linsize = hdr.height * hdr.width * (hdr.pixelfmt.bpp >> 3);
+ computed_pitch_or_linsize = hdr.height * hdr.width * (hdr.pixelfmt.bpp >> 3);
}
- }
+ if (computed_pitch_or_linsize != hdr.pitch_or_linsize)
+ {
+ g_printerr ("Unexpected 'pitch_or_linsize' (%u) set to %u\n",
+ hdr.pitch_or_linsize, computed_pitch_or_linsize);
+ hdr.pitch_or_linsize = computed_pitch_or_linsize;
+ }
if (hdr.pixelfmt.flags & DDPF_FOURCC)
{
@@ -295,6 +304,14 @@ read_dds (gchar *filename,
precision = GIMP_PRECISION_U8_GAMMA;
}
+ /* verify header information is accurate */
+ if (d.bpp < 1 ||
+ (hdr.pitch_or_linsize > (file_size - sizeof (hdr))))
+ {
+ fclose (fp);
+ g_printerr ("Invalid or corrupted DDS header");
+ return GIMP_PDB_EXECUTION_ERROR;
+ }
image = gimp_image_new_with_precision (hdr.width, hdr.height, type, precision);
if (image == -1)
@@ -908,6 +925,13 @@ load_layer (FILE *fp,
unsigned int size = hdr->pitch_or_linsize >> (2 * level);
unsigned int layerw;
int 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, current_position, SEEK_SET);
if (width < 1) width = 1;
if (height < 1) height = 1;
@@ -1011,6 +1035,12 @@ load_layer (FILE *fp,
else
size *= 16;
}
+ if (size > (file_size - current_position) ||
+ size > hdr->pitch_or_linsize)
+ {
+ g_printerr ("Requested data exceeds size of file.\n");
+ return FALSE;
+ }
if ((hdr->flags & DDSD_LINEARSIZE) &&
!fread (buf, size, 1, fp))
@@ -1049,7 +1079,14 @@ load_layer (FILE *fp,
n = 0;
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_printerr ("Requested data exceeds size of file.\n");
+ return FALSE;
+ }
if ((hdr->flags & DDSD_PITCH) &&
!fread (buf, width * d->bpp, 1, fp))
{