1 From 46bcd82800e37b0f5aead76184430ef2fe802748 Mon Sep 17 00:00:00 2001
2 From: Michael Natterer <mitch@gimp.org>
3 Date: Sun, 6 Nov 2016 21:34:43 +0100
4 Subject: Bug 773233 - CVE-2007-3126 - Gimp 2.3.14 allows context-dependent
7 ...to cause a denial of service (crash) via an ICO file with an
8 InfoHeader containing a Height of zero
10 Add some error handling to ico-load.c and bail out on zero width or height
11 icons. Also some formatting cleanup.
13 plug-ins/file-ico/ico-load.c | 103 ++++++++++++++++++++++++++-----------------
14 1 file changed, 62 insertions(+), 41 deletions(-)
16 diff --git a/plug-ins/file-ico/ico-load.c b/plug-ins/file-ico/ico-load.c
17 index c8091d3..8cce94f 100644
18 --- a/plug-ins/file-ico/ico-load.c
19 +++ b/plug-ins/file-ico/ico-load.c
20 @@ -124,15 +124,17 @@ static guint32
21 ico_read_init (FILE *fp)
25 /* read and check file header */
26 - if (!ico_read_int16 (fp, &header.reserved, 1)
27 - || !ico_read_int16 (fp, &header.resource_type, 1)
28 - || !ico_read_int16 (fp, &header.icon_count, 1)
29 - || header.reserved != 0
30 - || header.resource_type != 1)
31 + if (! ico_read_int16 (fp, &header.reserved, 1) ||
32 + ! ico_read_int16 (fp, &header.resource_type, 1) ||
33 + ! ico_read_int16 (fp, &header.icon_count, 1) ||
34 + header.reserved != 0 ||
35 + header.resource_type != 1)
40 return header.icon_count;
43 @@ -148,22 +150,25 @@ ico_read_size (FILE *fp,
47 - if ( fseek (fp, info->offset, SEEK_SET) < 0 )
48 + if (fseek (fp, info->offset, SEEK_SET) < 0)
51 ico_read_int32 (fp, &magic, 1);
53 if (magic == ICO_PNG_MAGIC)
55 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL,
61 info_ptr = png_create_info_struct (png_ptr);
65 png_destroy_read_struct (&png_ptr, NULL, NULL);
69 if (setjmp (png_jmpbuf (png_ptr)))
71 png_destroy_read_struct (&png_ptr, NULL, NULL);
72 @@ -182,8 +187,8 @@ ico_read_size (FILE *fp,
76 - if (ico_read_int32 (fp, &info->width, 1)
77 - && ico_read_int32 (fp, &info->height, 1))
78 + if (ico_read_int32 (fp, &info->width, 1) &&
79 + ico_read_int32 (fp, &info->height, 1))
82 D(("ico_read_size: ICO: %ix%i\n", info->width, info->height));
83 @@ -200,8 +205,9 @@ ico_read_size (FILE *fp,
87 -ico_read_info (FILE *fp,
89 +ico_read_info (FILE *fp,
94 IcoFileEntry *entries;
95 @@ -209,8 +215,11 @@ ico_read_info (FILE *fp,
97 /* read icon entries */
98 entries = g_new (IcoFileEntry, icon_count);
99 - if ( fread (entries, sizeof(IcoFileEntry), icon_count, fp) <= 0 )
100 + if (fread (entries, sizeof (IcoFileEntry), icon_count, fp) <= 0)
102 + g_set_error (error, G_FILE_ERROR, 0,
103 + _("Could not read '%lu' bytes"),
104 + sizeof (IcoFileEntry));
108 @@ -218,23 +227,33 @@ ico_read_info (FILE *fp,
109 info = g_new (IcoLoadInfo, icon_count);
110 for (i = 0; i < icon_count; i++)
112 - info[i].width = entries[i].width;
113 + info[i].width = entries[i].width;
114 info[i].height = entries[i].height;
115 - info[i].bpp = GUINT16_FROM_LE (entries[i].bpp);
116 - info[i].size = GUINT32_FROM_LE (entries[i].size);
117 + info[i].bpp = GUINT16_FROM_LE (entries[i].bpp);
118 + info[i].size = GUINT32_FROM_LE (entries[i].size);
119 info[i].offset = GUINT32_FROM_LE (entries[i].offset);
121 if (info[i].width == 0 || info[i].height == 0)
123 - ico_read_size (fp, info+i);
124 + ico_read_size (fp, info + i);
127 D(("ico_read_info: %ix%i (%i bits, size: %i, offset: %i)\n",
128 info[i].width, info[i].height, info[i].bpp,
129 info[i].size, info[i].offset));
131 + if (info[i].width == 0 || info[i].height == 0)
133 + g_set_error (error, G_FILE_ERROR, 0,
134 + _("Icon #%d has zero width or height"), i);
146 @@ -256,10 +275,10 @@ ico_read_png (FILE *fp,
149 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
153 info = png_create_info_struct (png_ptr);
157 png_destroy_read_struct (&png_ptr, NULL, NULL);
159 @@ -287,14 +306,14 @@ ico_read_png (FILE *fp,
161 case PNG_COLOR_TYPE_GRAY:
162 png_set_expand_gray_1_2_4_to_8 (png_ptr);
163 - if ( bit_depth == 16 )
164 + if (bit_depth == 16)
165 png_set_strip_16 (png_ptr);
166 png_set_gray_to_rgb (png_ptr);
167 png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
169 case PNG_COLOR_TYPE_GRAY_ALPHA:
170 png_set_expand_gray_1_2_4_to_8 (png_ptr);
171 - if ( bit_depth == 16 )
172 + if (bit_depth == 16)
173 png_set_strip_16 (png_ptr);
174 png_set_gray_to_rgb (png_ptr);
176 @@ -427,16 +446,18 @@ ico_read_icon (FILE *fp,
177 data.planes, data.image_size, data.bpp,
178 data.used_clrs, data.important_clrs));
180 - if (data.planes != 1
181 - || data.compression != 0)
182 + if (data.planes != 1 ||
183 + data.compression != 0)
185 D(("skipping image: invalid header\n"));
189 - if (data.bpp != 1 && data.bpp != 4
190 - && data.bpp != 8 && data.bpp != 24
192 + if (data.bpp != 1 &&
198 D(("skipping image: invalid depth: %i\n", data.bpp));
200 @@ -590,8 +611,8 @@ ico_load_layer (FILE *fp,
202 gchar name[ICO_MAXBUF];
204 - if ( fseek (fp, info->offset, SEEK_SET) < 0
205 - || !ico_read_int32 (fp, &first_bytes, 1) )
206 + if (fseek (fp, info->offset, SEEK_SET) < 0 ||
207 + ! ico_read_int32 (fp, &first_bytes, 1))
210 if (first_bytes == ICO_PNG_MAGIC)
211 @@ -643,7 +664,7 @@ ico_load_image (const gchar *filename,
212 gimp_filename_to_utf8 (filename));
214 fp = g_fopen (filename, "rb");
218 g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
219 _("Could not open '%s' for reading: %s"),
220 @@ -658,8 +679,8 @@ ico_load_image (const gchar *filename,
224 - info = ico_read_info (fp, icon_count);
226 + info = ico_read_info (fp, icon_count, error);
231 @@ -670,12 +691,12 @@ ico_load_image (const gchar *filename,
233 for (i = 0; i < icon_count; i++)
235 - if ( info[i].width > max_width )
236 + if (info[i].width > max_width)
237 max_width = info[i].width;
238 - if ( info[i].height > max_height )
239 + if (info[i].height > max_height)
240 max_height = info[i].height;
242 - if ( max_width <= 0 || max_height <= 0 )
243 + if (max_width <= 0 || max_height <= 0)
247 @@ -721,7 +742,7 @@ ico_load_thumbnail_image (const gchar *filename,
248 gimp_filename_to_utf8 (filename));
250 fp = g_fopen (filename, "rb");
254 g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
255 _("Could not open '%s' for reading: %s"),
256 @@ -730,7 +751,7 @@ ico_load_thumbnail_image (const gchar *filename,
259 icon_count = ico_read_init (fp);
265 @@ -739,8 +760,8 @@ ico_load_thumbnail_image (const gchar *filename,
266 D(("*** %s: Microsoft icon file, containing %i icon(s)\n",
267 filename, icon_count));
269 - info = ico_read_info (fp, icon_count);
271 + info = ico_read_info (fp, icon_count, error);
276 @@ -758,9 +779,9 @@ ico_load_thumbnail_image (const gchar *filename,
280 - else if ( w == info[i].width
281 - && h == info[i].height
282 - && info[i].bpp > bpp )
283 + else if (w == info[i].width &&
284 + h == info[i].height &&