File: plug-ins-fix-dicom-plug-in-ZDI-CAN-27863.patch

package info (click to toggle)
gimp 3.0.4-6.2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 210,548 kB
  • sloc: ansic: 842,405; lisp: 10,761; python: 10,318; cpp: 7,238; perl: 4,355; sh: 1,043; xml: 963; yacc: 609; lex: 348; javascript: 150; makefile: 43
file content (148 lines) | stat: -rw-r--r-- 5,349 bytes parent folder | download
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