blob: de82d6303371dbb160cb9a17894b4cc27057bc1c [file] [log] [blame]
Patrick Williamsb48b7b42016-08-17 15:04:38 -05001From 24e548a222f0aab4313d5ba8b04f0840b173000f Mon Sep 17 00:00:00 2001
2From: iwamatsu <iwamatsu@7c53e7cc-98ea-0310-8f1f-a0b24da60408>
3Date: Mon, 30 Aug 2010 01:24:54 +0000
4Subject: [PATCH 2/8] Fix image handling integer overflows
5
6Image loading memory allocation is based on the image width and height:
7 malloc(heigth * width * 3). Providing an image with large height and
8width values can cause the result of this calculation to exceed the
9maximum value of an unsigned int and thus causes an integer overflow.
10The result: too little memory is allocated and an heap overflow occurs.
11
12This patch was based by Niels Heinen <niels@freebsd.org>
13Thanks!
14
15Signed-off-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
16
17git-svn-id: svn://svn.berlios.de/slim/trunk@176 7c53e7cc-98ea-0310-8f1f-a0b24da60408
18---
19 const.h | 3 ++
20 jpeg.c | 51 +++++++++++++++-----------
21 png.c | 122 ++++++++++++++++++++++++++++++++------------------------------
22 3 files changed, 96 insertions(+), 80 deletions(-)
23
24diff --git a/const.h b/const.h
25index df0989c..a18c6f3 100644
26--- a/const.h
27+++ b/const.h
28@@ -42,4 +42,7 @@
29 // variables replaced in pre-session_cmd and post-session_cmd
30 #define USER_VAR "%user"
31
32+// max height/width for images
33+#define MAX_DIMENSION 10000
34+
35 #endif
36diff --git a/jpeg.c b/jpeg.c
37index 1cf106c..e1f8352 100644
38--- a/jpeg.c
39+++ b/jpeg.c
40@@ -22,16 +22,22 @@
41 #include <string.h>
42
43 #include <jpeglib.h>
44+#include "const.h"
45
46 int
47 read_jpeg(const char *filename, int *width, int *height, unsigned char **rgb)
48 {
49+ int ret = 0;
50 struct jpeg_decompress_struct cinfo;
51 struct jpeg_error_mgr jerr;
52 unsigned char *ptr = NULL;
53 unsigned int i, ipos;
54
55 FILE *infile = fopen(filename, "rb");
56+ if (infile == NULL) {
57+ fprintf(stderr, "Can not fopen file: %s\n",filename);
58+ return ret;
59+ }
60
61 cinfo.err = jpeg_std_error(&jerr);
62 jpeg_create_decompress(&cinfo);
63@@ -39,43 +45,39 @@ read_jpeg(const char *filename, int *width, int *height, unsigned char **rgb)
64 jpeg_read_header(&cinfo, TRUE);
65 jpeg_start_decompress(&cinfo);
66
67+ /* Prevent against integer overflow */
68+ if(cinfo.output_width >= MAX_DIMENSION || cinfo.output_height >= MAX_DIMENSION) {
69+ fprintf(stderr, "Unreasonable dimension found in file: %s\n",filename);
70+ goto close_file;
71+ }
72+
73 *width = cinfo.output_width;
74 *height = cinfo.output_height;
75
76 rgb[0] = malloc(3 * cinfo.output_width * cinfo.output_height);
77- if (rgb[0] == NULL)
78- {
79+ if (rgb[0] == NULL) {
80 fprintf(stderr, "Can't allocate memory for JPEG file.\n");
81- fclose(infile);
82- return(0);
83+ goto close_file;
84 }
85
86- if (cinfo.output_components == 3)
87- {
88+ if (cinfo.output_components == 3) {
89 ptr = rgb[0];
90- while (cinfo.output_scanline < cinfo.output_height)
91- {
92+ while (cinfo.output_scanline < cinfo.output_height) {
93 jpeg_read_scanlines(&cinfo, &ptr, 1);
94 ptr += 3 * cinfo.output_width;
95 }
96- }
97- else if (cinfo.output_components == 1)
98- {
99+ } else if (cinfo.output_components == 1) {
100 ptr = malloc(cinfo.output_width);
101- if (ptr == NULL)
102- {
103+ if (ptr == NULL) {
104 fprintf(stderr, "Can't allocate memory for JPEG file.\n");
105- fclose(infile);
106- return(0);
107+ goto rgb_free;
108 }
109
110 ipos = 0;
111- while (cinfo.output_scanline < cinfo.output_height)
112- {
113+ while (cinfo.output_scanline < cinfo.output_height) {
114 jpeg_read_scanlines(&cinfo, &ptr, 1);
115
116- for (i = 0; i < cinfo.output_width; i++)
117- {
118+ for (i = 0; i < cinfo.output_width; i++) {
119 memset(rgb[0] + ipos, ptr[i], 3);
120 ipos += 3;
121 }
122@@ -85,9 +87,16 @@ read_jpeg(const char *filename, int *width, int *height, unsigned char **rgb)
123 }
124
125 jpeg_finish_decompress(&cinfo);
126- jpeg_destroy_decompress(&cinfo);
127
128+ ret = 1;
129+ goto close_file;
130+
131+rgb_free:
132+ free(rgb[0]);
133+
134+close_file:
135+ jpeg_destroy_decompress(&cinfo);
136 fclose(infile);
137
138- return(1);
139+ return(ret);
140 }
141diff --git a/png.c b/png.c
142index a2661c6..5c086c6 100644
143--- a/png.c
144+++ b/png.c
145@@ -22,12 +22,13 @@
146 #include <stdlib.h>
147
148 #include <png.h>
149+#include "const.h"
150
151 int
152 read_png(const char *filename, int *width, int *height, unsigned char **rgb,
153 unsigned char **alpha)
154 {
155- FILE *infile = fopen(filename, "rb");
156+ int ret = 0;
157
158 png_structp png_ptr;
159 png_infop info_ptr;
160@@ -38,31 +39,27 @@ read_png(const char *filename, int *width, int *height, unsigned char **rgb,
161 int bit_depth, color_type, interlace_type;
162 int i;
163
164+ FILE *infile = fopen(filename, "rb");
165+ if (infile == NULL) {
166+ fprintf(stderr, "Can not fopen file: %s\n",filename);
167+ return ret;
168+ }
169+
170 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
171 (png_voidp) NULL,
172 (png_error_ptr) NULL,
173 (png_error_ptr) NULL);
174- if (!png_ptr)
175- {
176- fclose(infile);
177- return(0);
178- }
179+ if (!png_ptr)
180+ goto file_close;
181
182 info_ptr = png_create_info_struct(png_ptr);
183- if (!info_ptr)
184- {
185+ if (!info_ptr) {
186 png_destroy_read_struct(&png_ptr, (png_infopp) NULL,
187 (png_infopp) NULL);
188- fclose(infile);
189- return(0);
190 }
191
192 if (setjmp(png_ptr->jmpbuf))
193- {
194- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
195- fclose(infile);
196- return(0);
197- }
198+ goto png_destroy;
199
200 png_init_io(png_ptr, infile);
201 png_read_info(png_ptr, info_ptr);
202@@ -70,18 +67,23 @@ read_png(const char *filename, int *width, int *height, unsigned char **rgb,
203 png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
204 &interlace_type, (int *) NULL, (int *) NULL);
205
206+ /* Prevent against integer overflow */
207+ if(w >= MAX_DIMENSION || h >= MAX_DIMENSION) {
208+ fprintf(stderr, "Unreasonable dimension found in file: %s\n",filename);
209+ goto png_destroy;
210+ }
211+
212 *width = (int) w;
213 *height = (int) h;
214
215 if (color_type == PNG_COLOR_TYPE_RGB_ALPHA
216- || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
217- {
218- alpha[0] = malloc(*width * *height);
219- if (alpha[0] == NULL)
220- {
221- fprintf(stderr, "Can't allocate memory for alpha channel in PNG file.\n");
222- return(0);
223- }
224+ || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
225+ alpha[0] = malloc(*width * *height);
226+ if (alpha[0] == NULL)
227+ {
228+ fprintf(stderr, "Can't allocate memory for alpha channel in PNG file.\n");
229+ goto png_destroy;
230+ }
231 }
232
233 /* Change a paletted/grayscale image to RGB */
234@@ -94,68 +96,70 @@ read_png(const char *filename, int *width, int *height, unsigned char **rgb,
235 png_set_gray_to_rgb(png_ptr);
236
237 /* If the PNG file has 16 bits per channel, strip them down to 8 */
238- if (bit_depth == 16) png_set_strip_16(png_ptr);
239+ if (bit_depth == 16)
240+ png_set_strip_16(png_ptr);
241
242 /* use 1 byte per pixel */
243 png_set_packing(png_ptr);
244
245 row_pointers = malloc(*height * sizeof(png_bytep));
246- if (row_pointers == NULL)
247- {
248+ if (row_pointers == NULL) {
249 fprintf(stderr, "Can't allocate memory for PNG file.\n");
250- return(0);
251+ goto png_destroy;
252 }
253
254- for (i = 0; i < *height; i++)
255- {
256+ for (i = 0; i < *height; i++) {
257 row_pointers[i] = malloc(4 * *width);
258- if (row_pointers == NULL)
259- {
260+ if (row_pointers == NULL) {
261 fprintf(stderr, "Can't allocate memory for PNG line.\n");
262- return(0);
263+ goto rows_free;
264 }
265 }
266
267 png_read_image(png_ptr, row_pointers);
268
269 rgb[0] = malloc(3 * *width * *height);
270- if (rgb[0] == NULL)
271- {
272+ if (rgb[0] == NULL) {
273 fprintf(stderr, "Can't allocate memory for PNG file.\n");
274- return(0);
275+ goto rows_free;
276 }
277
278 if (alpha[0] == NULL)
279 {
280- ptr = rgb[0];
281- for (i = 0; i < *height; i++)
282- {
283- memcpy(ptr, row_pointers[i], 3 * *width);
284- ptr += 3 * *width;
285- }
286- }
287- else
288- {
289- int j;
290- ptr = rgb[0];
291- for (i = 0; i < *height; i++)
292- {
293- int ipos = 0;
294- for (j = 0; j < *width; j++)
295- {
296- *ptr++ = row_pointers[i][ipos++];
297- *ptr++ = row_pointers[i][ipos++];
298- *ptr++ = row_pointers[i][ipos++];
299- alpha[0][i * *width + j] = row_pointers[i][ipos++];
300+ ptr = rgb[0];
301+ for (i = 0; i < *height; i++) {
302+ memcpy(ptr, row_pointers[i], 3 * *width);
303+ ptr += 3 * *width;
304+ }
305+ } else {
306+ int j;
307+ ptr = rgb[0];
308+ for (i = 0; i < *height; i++) {
309+ int ipos = 0;
310+ for (j = 0; j < *width; j++) {
311+ *ptr++ = row_pointers[i][ipos++];
312+ *ptr++ = row_pointers[i][ipos++];
313+ *ptr++ = row_pointers[i][ipos++];
314+ alpha[0][i * *width + j] = row_pointers[i][ipos++];
315+ }
316 }
317- }
318 }
319
320- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
321+ ret = 1; /* data reading is OK */
322+
323+rows_free:
324+ for (i = 0; i < *height; i++) {
325+ if (row_pointers[i] != NULL ) {
326+ free(row_pointers[i]);
327+ }
328+ }
329
330- for (i = 0; i < *height; i++) free(row_pointers[i]);
331 free(row_pointers);
332
333+png_destroy:
334+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
335+
336+file_close:
337 fclose(infile);
338- return(1);
339+ return(ret);
340 }
341--
3421.6.6.1
343