aboutsummaryrefslogtreecommitdiffstats
path: root/community/freeimage/CVE-2019-12211_3.patch
blob: 9e825a51e55fc06204918b70fcae3f33c034019e (plain)
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
Index: FreeImage/trunk/Source/FreeImage/PluginTIFF.cpp
===================================================================
--- trunk/Source/FreeImage/PluginTIFF.cpp	(revision 1824)
+++ trunk/Source/FreeImage/PluginTIFF.cpp	(revision 1825)
@@ -122,9 +122,14 @@
 static int s_format_id;
 
 typedef struct {
+	//! FreeImage IO functions
     FreeImageIO *io;
+	//! FreeImage handle
 	fi_handle handle;
+	//! LibTIFF handle
 	TIFF *tif;
+	//! Count the number of thumbnails already read (used to avoid recursion on loading)
+	unsigned thumbnailCount;
 } fi_TIFFIO;
 
 // ----------------------------------------------------------
@@ -184,10 +189,8 @@
 */
 TIFF *
 TIFFFdOpen(thandle_t handle, const char *name, const char *mode) {
-	TIFF *tif;
-	
 	// Open the file; the callback will set everything up
-	tif = TIFFClientOpen(name, mode, handle,
+	TIFF *tif = TIFFClientOpen(name, mode, handle,
 	    _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
 	    _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
 
@@ -460,12 +463,10 @@
 			}
 			
 		}
-		else {
-
-			dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+		else if (bpp <= 32) {
+			dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
 		}
 
-
 	} else {
 		// other bitmap types
 		
@@ -1067,9 +1068,12 @@
 Open(FreeImageIO *io, fi_handle handle, BOOL read) {
 	// wrapper for TIFF I/O
 	fi_TIFFIO *fio = (fi_TIFFIO*)malloc(sizeof(fi_TIFFIO));
-	if(!fio) return NULL;
+	if (!fio) {
+		return NULL;
+	}
 	fio->io = io;
 	fio->handle = handle;
+	fio->thumbnailCount = 0;
 
 	if (read) {
 		fio->tif = TIFFFdOpen((thandle_t)fio, "", "r");
@@ -1125,7 +1129,28 @@
 */
 static BOOL 
 IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) {
+	// get the pixel depth in bits
+	const uint16 pixel_depth = bitspersample * samplesperpixel;
 
+	// check for a supported pixel depth
+	switch (pixel_depth) {
+		case 1:
+		case 4:
+		case 8:
+		case 16:
+		case 24:
+		case 32:
+		case 48:
+		case 64:
+		case 96:
+		case 128:
+			// OK, go on
+			break;
+		default:
+			// unsupported pixel depth
+			return FALSE;
+	}
+
 	switch(bitspersample) {
 		case 1:
 		case 4:
@@ -1165,6 +1190,8 @@
 		default:
 			return FALSE;
 	}
+	
+	return FALSE;
 }
 
 static TIFFLoadMethod  
@@ -1254,16 +1281,31 @@
 static void 
 ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) {
 	FIBITMAP* thumbnail = NULL;
+
+	fi_TIFFIO *fio = (fi_TIFFIO*)data;
+
+	/*
+	Thumbnail loading can cause recursions because of the way 
+	functions TIFFLastDirectory and TIFFSetSubDirectory are working.
+	We use here a hack to count the number of times the ReadThumbnail function was called. 
+	We only allow one call, check for this
+	*/
+	if (fio->thumbnailCount > 0) {
+		return;
+	}
+	else {
+		// update the thumbnail count (used to avoid recursion)
+		fio->thumbnailCount++;
+	}
 	
 	// read exif thumbnail (IFD 1) ...
 	
-	/*
-	// this code can cause unwanted recursion causing an overflow, it is thus disabled until we have a better solution
-	// do we really need to read a thumbnail from the Exif segment ? knowing that TIFF store the thumbnail in the subIFD ...
-	// 
 	toff_t exif_offset = 0;
 	if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) {
 		
+		// this code can cause unwanted recursion causing an overflow, because of the way TIFFLastDirectory work
+		// => this is checked using 
+
 		if(!TIFFLastDirectory(tiff)) {
 			// save current position
 			const long tell_pos = io->tell_proc(handle);
@@ -1273,15 +1315,15 @@
 			int page = 1;
 			int flags = TIFF_DEFAULT;
 			thumbnail = Load(io, handle, page, flags, data);
+
 			// store the thumbnail (remember to release it before return)
 			FreeImage_SetThumbnail(dib, thumbnail);
-			
+		
 			// restore current position
 			io->seek_proc(handle, tell_pos, SEEK_SET);
 			TIFFSetDirectory(tiff, cur_dir);
 		}
 	}
-	*/
 	
 	// ... or read the first subIFD
 	
@@ -1297,6 +1339,8 @@
 				// save current position
 				const long tell_pos = io->tell_proc(handle);
 				const uint16 cur_dir = TIFFCurrentDirectory(tiff);
+
+				// this code can cause unwanted recursion causing an overflow, because of the way TIFFSetSubDirectory work
 				
 				if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) {
 					// load the thumbnail
@@ -1303,6 +1347,7 @@
 					int page = -1; 
 					int flags = TIFF_DEFAULT;
 					thumbnail = Load(io, handle, page, flags, data);
+
 					// store the thumbnail (remember to release it before return)
 					FreeImage_SetThumbnail(dib, thumbnail);
 				}
@@ -2058,7 +2103,7 @@
 				}
 
 				// calculate src line and dst pitch
-				int dst_pitch = FreeImage_GetPitch(dib);
+				unsigned dst_pitch = FreeImage_GetPitch(dib);
 				uint32 tileRowSize = (uint32)TIFFTileRowSize(tif);
 				uint32 imageRowSize = (uint32)TIFFScanlineSize(tif);
 
@@ -2088,7 +2133,7 @@
 						BYTE *src_bits = tileBuffer;
 						BYTE *dst_bits = bits + rowSize;
 						for(int k = 0; k < nrows; k++) {
-							memcpy(dst_bits, src_bits, src_line);
+							memcpy(dst_bits, src_bits, MIN(dst_pitch, src_line));
 							src_bits += tileRowSize;
 							dst_bits -= dst_pitch;
 						}