1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
From: Jacob Boerema <jgboerema@gmail.com>
Date: Wed, 3 Sep 2025 13:31:45 -0400
Subject: plug-ins: fix dicom plug-in ZDI-CAN-27863
Origin: https://gitlab.gnome.org/GNOME/gimp/-/commit/0f309f9a8d82f43fa01383bc5a5c41d28727d9e3
Bug-Debian: https://bugs.debian.org/1116459
Bug: https://gitlab.gnome.org/GNOME/gimp/-/issues/14811
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2025-10922
GIMP DCM File Parsing Heap-based Buffer Overflow Remote Code Execution
Vulnerability
This adds more safety checks and sets actual GError's instead of just
calling gimp_quit.
Closes #14811
---
plug-ins/common/file-dicom.c | 65 ++++++++++++++++++++++++++++--------
1 file changed, 51 insertions(+), 14 deletions(-)
diff --git a/plug-ins/common/file-dicom.c b/plug-ins/common/file-dicom.c
index 31039050f27a..a11a13ef4058 100644
--- a/plug-ins/common/file-dicom.c
+++ b/plug-ins/common/file-dicom.c
@@ -344,6 +344,7 @@ load_image (GFile *file,
gint bits_stored = 0;
gint high_bit = 0;
guint8 *pix_buf = NULL;
+ guint64 pixbuf_size = 0;
gboolean is_signed = FALSE;
guint8 in_sequence = 0;
gboolean implicit_encoding = FALSE;
@@ -399,6 +400,7 @@ load_image (GFile *file,
guint16 ctx_us;
guint8 *value;
guint32 tag;
+ size_t actual_read;
if (fread (&group_word, 1, 2, dicom) == 0)
break;
@@ -503,15 +505,24 @@ load_image (GFile *file,
if (element_length >= (G_MAXUINT - 6))
{
- g_message ("'%s' seems to have an incorrect value field length.",
- gimp_file_get_utf8_name (file));
- gimp_quit ();
+ g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
+ _("'%s' has an an incorrect value for field size. Possibly corrupt image."),
+ gimp_file_get_utf8_name (file));
+ g_free (dicominfo);
+ fclose (dicom);
+ return NULL;
}
/* Read contents. Allocate a bit more to make room for casts to int
below. */
value = g_new0 (guint8, element_length + 4);
- fread (value, 1, element_length, dicom);
+ actual_read = fread (value, 1, element_length, dicom);
+ if (actual_read < element_length)
+ {
+ g_warning ("Missing data: needed %u bytes, got %u. Possibly corrupt image.",
+ element_length, (guint32) actual_read);
+ element_length = actual_read;
+ }
/* ignore everything inside of a sequence */
if (in_sequence)
@@ -524,7 +535,7 @@ load_image (GFile *file,
if (big_endian && group_word != 0x0002)
ctx_us = GUINT16_SWAP_LE_BE (ctx_us);
- g_debug ("group: %04x, element: %04x, length: %d",
+ g_debug ("group: %04x, element: %04x, length: %u",
group_word, element_word, element_length);
g_debug ("Value: %s", (char*)value);
/* Recognize some critical tags */
@@ -658,6 +669,7 @@ load_image (GFile *file,
if (group_word == 0x7fe0 && element_word == 0x0010)
{
pix_buf = value;
+ pixbuf_size = element_length;
}
else
{
@@ -688,25 +700,50 @@ load_image (GFile *file,
}
}
+ g_debug ("Bpp: %d, wxh: %u x %u, spp: %d\n", bpp, width, height, samples_per_pixel);
+
if ((bpp != 8) && (bpp != 16))
{
- g_message ("'%s' has a bpp of %d which GIMP cannot handle.",
- gimp_file_get_utf8_name (file), bpp);
- gimp_quit ();
+ g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
+ _("'%s' has a bpp of %d which GIMP cannot handle."),
+ gimp_file_get_utf8_name (file), bpp);
+ g_free (pix_buf);
+ g_free (dicominfo);
+ fclose (dicom);
+ return NULL;
}
if ((width > GIMP_MAX_IMAGE_SIZE) || (height > GIMP_MAX_IMAGE_SIZE))
{
- g_message ("'%s' has a larger image size (%d x %d) than GIMP can handle.",
- gimp_file_get_utf8_name (file), width, height);
- gimp_quit ();
+ g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
+ _("'%s' has a larger image size (%d x %d) than GIMP can handle."),
+ gimp_file_get_utf8_name (file), width, height);
+ g_free (pix_buf);
+ g_free (dicominfo);
+ fclose (dicom);
+ return NULL;
}
if (samples_per_pixel > 3)
{
- g_message ("'%s' has samples per pixel of %d which GIMP cannot handle.",
- gimp_file_get_utf8_name (file), samples_per_pixel);
- gimp_quit ();
+ g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
+ _("'%s' has samples per pixel of %d which GIMP cannot handle."),
+ gimp_file_get_utf8_name (file), samples_per_pixel);
+ g_free (pix_buf);
+ g_free (dicominfo);
+ fclose (dicom);
+ return NULL;
+ }
+
+ if ((guint64) width * height * (bpp >> 3) * samples_per_pixel > pixbuf_size)
+ {
+ g_set_error (error, GIMP_PLUG_IN_ERROR, 0,
+ _("'%s' has not enough pixel data. Possibly corrupt image."),
+ gimp_file_get_utf8_name (file));
+ g_free (pix_buf);
+ g_free (dicominfo);
+ fclose (dicom);
+ return NULL;
}
dicominfo->width = width;
--
2.51.0
|