1 |
From 323ecb73f7bf36788fb7066eb2d6678830cd5de7 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 |
5 |
attackers... |
6 |
|
7 |
...to cause a denial of service (crash) via an ICO file with an |
8 |
InfoHeader containing a Height of zero |
9 |
|
10 |
Add some error handling to ico-load.c and bail out on zero width or height |
11 |
icons. Also some formatting cleanup. |
12 |
|
13 |
(cherry picked from commit 46bcd82800e37b0f5aead76184430ef2fe802748) |
14 |
--- |
15 |
plug-ins/file-ico/ico-load.c | 103 ++++++++++++++++++++++++++----------------- |
16 |
1 file changed, 62 insertions(+), 41 deletions(-) |
17 |
|
18 |
diff --git a/plug-ins/file-ico/ico-load.c b/plug-ins/file-ico/ico-load.c |
19 |
index fde543a..0075eab 100644 |
20 |
--- a/plug-ins/file-ico/ico-load.c |
21 |
+++ b/plug-ins/file-ico/ico-load.c |
22 |
@@ -124,15 +124,17 @@ static guint32 |
23 |
ico_read_init (FILE *fp) |
24 |
{ |
25 |
IcoFileHeader header; |
26 |
+ |
27 |
/* read and check file header */ |
28 |
- if (!ico_read_int16 (fp, &header.reserved, 1) |
29 |
- || !ico_read_int16 (fp, &header.resource_type, 1) |
30 |
- || !ico_read_int16 (fp, &header.icon_count, 1) |
31 |
- || header.reserved != 0 |
32 |
- || header.resource_type != 1) |
33 |
+ if (! ico_read_int16 (fp, &header.reserved, 1) || |
34 |
+ ! ico_read_int16 (fp, &header.resource_type, 1) || |
35 |
+ ! ico_read_int16 (fp, &header.icon_count, 1) || |
36 |
+ header.reserved != 0 || |
37 |
+ header.resource_type != 1) |
38 |
{ |
39 |
return 0; |
40 |
} |
41 |
+ |
42 |
return header.icon_count; |
43 |
} |
44 |
|
45 |
@@ -148,22 +150,25 @@ ico_read_size (FILE *fp, |
46 |
gint32 color_type; |
47 |
guint32 magic; |
48 |
|
49 |
- if ( fseek (fp, info->offset, SEEK_SET) < 0 ) |
50 |
+ if (fseek (fp, info->offset, SEEK_SET) < 0) |
51 |
return FALSE; |
52 |
|
53 |
ico_read_int32 (fp, &magic, 1); |
54 |
+ |
55 |
if (magic == ICO_PNG_MAGIC) |
56 |
{ |
57 |
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, |
58 |
NULL); |
59 |
- if (! png_ptr ) |
60 |
+ if (! png_ptr) |
61 |
return FALSE; |
62 |
+ |
63 |
info_ptr = png_create_info_struct (png_ptr); |
64 |
- if (! info_ptr ) |
65 |
+ if (! info_ptr) |
66 |
{ |
67 |
png_destroy_read_struct (&png_ptr, NULL, NULL); |
68 |
return FALSE; |
69 |
} |
70 |
+ |
71 |
if (setjmp (png_jmpbuf (png_ptr))) |
72 |
{ |
73 |
png_destroy_read_struct (&png_ptr, NULL, NULL); |
74 |
@@ -182,8 +187,8 @@ ico_read_size (FILE *fp, |
75 |
} |
76 |
else if (magic == 40) |
77 |
{ |
78 |
- if (ico_read_int32 (fp, &info->width, 1) |
79 |
- && ico_read_int32 (fp, &info->height, 1)) |
80 |
+ if (ico_read_int32 (fp, &info->width, 1) && |
81 |
+ ico_read_int32 (fp, &info->height, 1)) |
82 |
{ |
83 |
info->height /= 2; |
84 |
D(("ico_read_size: ICO: %ix%i\n", info->width, info->height)); |
85 |
@@ -200,8 +205,9 @@ ico_read_size (FILE *fp, |
86 |
} |
87 |
|
88 |
static IcoLoadInfo* |
89 |
-ico_read_info (FILE *fp, |
90 |
- gint icon_count) |
91 |
+ico_read_info (FILE *fp, |
92 |
+ gint icon_count, |
93 |
+ GError **error) |
94 |
{ |
95 |
gint i; |
96 |
IcoFileEntry *entries; |
97 |
@@ -209,8 +215,11 @@ ico_read_info (FILE *fp, |
98 |
|
99 |
/* read icon entries */ |
100 |
entries = g_new (IcoFileEntry, icon_count); |
101 |
- if ( fread (entries, sizeof(IcoFileEntry), icon_count, fp) <= 0 ) |
102 |
+ if (fread (entries, sizeof (IcoFileEntry), icon_count, fp) <= 0) |
103 |
{ |
104 |
+ g_set_error (error, G_FILE_ERROR, 0, |
105 |
+ _("Could not read '%lu' bytes"), |
106 |
+ sizeof (IcoFileEntry)); |
107 |
g_free (entries); |
108 |
return NULL; |
109 |
} |
110 |
@@ -218,23 +227,33 @@ ico_read_info (FILE *fp, |
111 |
info = g_new (IcoLoadInfo, icon_count); |
112 |
for (i = 0; i < icon_count; i++) |
113 |
{ |
114 |
- info[i].width = entries[i].width; |
115 |
+ info[i].width = entries[i].width; |
116 |
info[i].height = entries[i].height; |
117 |
- info[i].bpp = GUINT16_FROM_LE (entries[i].bpp); |
118 |
- info[i].size = GUINT32_FROM_LE (entries[i].size); |
119 |
+ info[i].bpp = GUINT16_FROM_LE (entries[i].bpp); |
120 |
+ info[i].size = GUINT32_FROM_LE (entries[i].size); |
121 |
info[i].offset = GUINT32_FROM_LE (entries[i].offset); |
122 |
|
123 |
if (info[i].width == 0 || info[i].height == 0) |
124 |
{ |
125 |
- ico_read_size (fp, info+i); |
126 |
+ ico_read_size (fp, info + i); |
127 |
} |
128 |
|
129 |
D(("ico_read_info: %ix%i (%i bits, size: %i, offset: %i)\n", |
130 |
info[i].width, info[i].height, info[i].bpp, |
131 |
info[i].size, info[i].offset)); |
132 |
+ |
133 |
+ if (info[i].width == 0 || info[i].height == 0) |
134 |
+ { |
135 |
+ g_set_error (error, G_FILE_ERROR, 0, |
136 |
+ _("Icon #%d has zero width or height"), i); |
137 |
+ g_free (info); |
138 |
+ g_free (entries); |
139 |
+ return NULL; |
140 |
+ } |
141 |
} |
142 |
|
143 |
g_free (entries); |
144 |
+ |
145 |
return info; |
146 |
} |
147 |
|
148 |
@@ -256,10 +275,10 @@ ico_read_png (FILE *fp, |
149 |
gint i; |
150 |
|
151 |
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); |
152 |
- if (! png_ptr ) |
153 |
+ if (! png_ptr) |
154 |
return FALSE; |
155 |
info = png_create_info_struct (png_ptr); |
156 |
- if (! info ) |
157 |
+ if (! info) |
158 |
{ |
159 |
png_destroy_read_struct (&png_ptr, NULL, NULL); |
160 |
return FALSE; |
161 |
@@ -287,14 +306,14 @@ ico_read_png (FILE *fp, |
162 |
{ |
163 |
case PNG_COLOR_TYPE_GRAY: |
164 |
png_set_expand_gray_1_2_4_to_8 (png_ptr); |
165 |
- if ( bit_depth == 16 ) |
166 |
+ if (bit_depth == 16) |
167 |
png_set_strip_16 (png_ptr); |
168 |
png_set_gray_to_rgb (png_ptr); |
169 |
png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER); |
170 |
break; |
171 |
case PNG_COLOR_TYPE_GRAY_ALPHA: |
172 |
png_set_expand_gray_1_2_4_to_8 (png_ptr); |
173 |
- if ( bit_depth == 16 ) |
174 |
+ if (bit_depth == 16) |
175 |
png_set_strip_16 (png_ptr); |
176 |
png_set_gray_to_rgb (png_ptr); |
177 |
break; |
178 |
@@ -427,16 +446,18 @@ ico_read_icon (FILE *fp, |
179 |
data.planes, data.image_size, data.bpp, |
180 |
data.used_clrs, data.important_clrs)); |
181 |
|
182 |
- if (data.planes != 1 |
183 |
- || data.compression != 0) |
184 |
+ if (data.planes != 1 || |
185 |
+ data.compression != 0) |
186 |
{ |
187 |
D(("skipping image: invalid header\n")); |
188 |
return FALSE; |
189 |
} |
190 |
|
191 |
- if (data.bpp != 1 && data.bpp != 4 |
192 |
- && data.bpp != 8 && data.bpp != 24 |
193 |
- && data.bpp != 32) |
194 |
+ if (data.bpp != 1 && |
195 |
+ data.bpp != 4 && |
196 |
+ data.bpp != 8 && |
197 |
+ data.bpp != 24 && |
198 |
+ data.bpp != 32) |
199 |
{ |
200 |
D(("skipping image: invalid depth: %i\n", data.bpp)); |
201 |
return FALSE; |
202 |
@@ -591,8 +612,8 @@ ico_load_layer (FILE *fp, |
203 |
GimpPixelRgn pixel_rgn; |
204 |
gchar buf [ICO_MAXBUF]; |
205 |
|
206 |
- if ( fseek (fp, info->offset, SEEK_SET) < 0 |
207 |
- || !ico_read_int32 (fp, &first_bytes, 1) ) |
208 |
+ if (fseek (fp, info->offset, SEEK_SET) < 0 || |
209 |
+ ! ico_read_int32 (fp, &first_bytes, 1)) |
210 |
return -1; |
211 |
|
212 |
if (first_bytes == ICO_PNG_MAGIC) |
213 |
@@ -645,7 +666,7 @@ ico_load_image (const gchar *filename, |
214 |
gimp_filename_to_utf8 (filename)); |
215 |
|
216 |
fp = g_fopen (filename, "rb"); |
217 |
- if (! fp ) |
218 |
+ if (! fp) |
219 |
{ |
220 |
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), |
221 |
_("Could not open '%s' for reading: %s"), |
222 |
@@ -660,8 +681,8 @@ ico_load_image (const gchar *filename, |
223 |
return -1; |
224 |
} |
225 |
|
226 |
- info = ico_read_info (fp, icon_count); |
227 |
- if (!info) |
228 |
+ info = ico_read_info (fp, icon_count, error); |
229 |
+ if (! info) |
230 |
{ |
231 |
fclose (fp); |
232 |
return -1; |
233 |
@@ -672,12 +693,12 @@ ico_load_image (const gchar *filename, |
234 |
max_height = 0; |
235 |
for (i = 0; i < icon_count; i++) |
236 |
{ |
237 |
- if ( info[i].width > max_width ) |
238 |
+ if (info[i].width > max_width) |
239 |
max_width = info[i].width; |
240 |
- if ( info[i].height > max_height ) |
241 |
+ if (info[i].height > max_height) |
242 |
max_height = info[i].height; |
243 |
} |
244 |
- if ( max_width <= 0 || max_height <= 0 ) |
245 |
+ if (max_width <= 0 || max_height <= 0) |
246 |
{ |
247 |
g_free (info); |
248 |
fclose (fp); |
249 |
@@ -723,7 +744,7 @@ ico_load_thumbnail_image (const gchar *filename, |
250 |
gimp_filename_to_utf8 (filename)); |
251 |
|
252 |
fp = g_fopen (filename, "rb"); |
253 |
- if (! fp ) |
254 |
+ if (! fp) |
255 |
{ |
256 |
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), |
257 |
_("Could not open '%s' for reading: %s"), |
258 |
@@ -732,7 +753,7 @@ ico_load_thumbnail_image (const gchar *filename, |
259 |
} |
260 |
|
261 |
icon_count = ico_read_init (fp); |
262 |
- if (! icon_count ) |
263 |
+ if (! icon_count) |
264 |
{ |
265 |
fclose (fp); |
266 |
return -1; |
267 |
@@ -741,8 +762,8 @@ ico_load_thumbnail_image (const gchar *filename, |
268 |
D(("*** %s: Microsoft icon file, containing %i icon(s)\n", |
269 |
filename, icon_count)); |
270 |
|
271 |
- info = ico_read_info (fp, icon_count); |
272 |
- if (! info ) |
273 |
+ info = ico_read_info (fp, icon_count, error); |
274 |
+ if (! info) |
275 |
{ |
276 |
fclose (fp); |
277 |
return -1; |
278 |
@@ -760,9 +781,9 @@ ico_load_thumbnail_image (const gchar *filename, |
279 |
|
280 |
match = i; |
281 |
} |
282 |
- else if ( w == info[i].width |
283 |
- && h == info[i].height |
284 |
- && info[i].bpp > bpp ) |
285 |
+ else if (w == info[i].width && |
286 |
+ h == info[i].height && |
287 |
+ info[i].bpp > bpp) |
288 |
{ |
289 |
/* better quality */ |
290 |
bpp = info[i].bpp; |
291 |
-- |
292 |
cgit v0.12 |
293 |
|