From: Alx Sa Date: Fri, 27 Oct 2023 22:04:48 +0000 Subject: plug-ins: Fix DDS import regression from 7db71cd0 Origin: https://gitlab.gnome.org/GNOME/gimp/-/commit/e92f279c97282a2b20dca0d923db7465f2057703 Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2023-44441 Bug-Debian: https://bugs.debian.org/1055984 @Wormnest pointed out that compressed files are likely smaller than width * height * bps, so our check to prevent ZDI-CAN-22093 also caught valid files. The size check is removed from load_image () and moved to load_layer () before the two fread() functions, as we know exactly how much we'll try to read at that point. (Backport of 8faad92e) --- plug-ins/file-dds/ddsread.c | 39 +++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/plug-ins/file-dds/ddsread.c b/plug-ins/file-dds/ddsread.c index 98e122de8aff..74368d04e41a 100644 --- a/plug-ins/file-dds/ddsread.c +++ b/plug-ins/file-dds/ddsread.c @@ -191,16 +191,6 @@ read_dds (gchar *filename, } } - /* 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; - } - if (hdr.pixelfmt.flags & DDPF_FOURCC) { /* fourcc is dXt* or rXgb */ @@ -310,6 +300,15 @@ 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_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 == -1) @@ -923,6 +922,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; @@ -1027,6 +1033,12 @@ load_layer (FILE *fp, size *= 16; } + if (size > (file_size - current_position)) + { + g_message ("Requested data exceeds size of file.\n"); + return 0; + } + if ((hdr->flags & DDSD_LINEARSIZE) && !fread (buf, size, 1, fp)) { @@ -1065,6 +1077,13 @@ load_layer (FILE *fp, gimp_progress_update ((double)y / (double)hdr->height); } + current_position = ftell (fp); + if ((width * d->bpp) > (file_size - current_position)) + { + g_message ("Requested data exceeds size of file.\n"); + return 0; + } + if ((hdr->flags & DDSD_PITCH) && !fread (buf, width * d->bpp, 1, fp)) { -- 2.42.0