summaryrefslogtreecommitdiff
path: root/media-libs/freeimage/files/freeimage-3.18.0-CVE-2019-12211-CVE-2019-12213.patch
blob: fc861854509c90130944f05b0aa14ab724428019 (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
188
189
190
191
192
193
commit 1826164f90d97b7207247ad268fd2622cd1c6717
Author: drolon <drolon@f6e0daa0-2725-47c6-9c0b-5e6e9cdd0720>
Date:   Mon Nov 11 05:45:27 2019 +0000

    improved TIFF plugin when working with malicious images
    
    git-svn-id: https://svn.code.sf.net/p/freeimage/svn@1825 f6e0daa0-2725-47c6-9c0b-5e6e9cdd0720

diff --git a/Source/FreeImage/PluginTIFF.cpp b/Source/FreeImage/PluginTIFF.cpp
index f85c2201..a8053196 100644
--- a/Source/FreeImage/PluginTIFF.cpp
+++ b/Source/FreeImage/PluginTIFF.cpp
@@ -122,9 +122,14 @@ static void ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *t
 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 @@ Open a TIFF file descriptor for reading or writing
 */
 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 @@ CreateImageType(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, ui
 			}
 			
 		}
-		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 @@ static void * DLL_CALLCONV
 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,6 +1129,27 @@ check for uncommon bitspersample values (e.g. 10, 12, ...)
 */
 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:
@@ -1165,6 +1190,8 @@ IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesper
 		default:
 			return FALSE;
 	}
+	
+	return FALSE;
 }
 
 static TIFFLoadMethod  
@@ -1254,16 +1281,31 @@ Read embedded thumbnail
 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 @@ ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMA
 			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,12 +1339,15 @@ ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMA
 				// 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
 					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 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
 				}
 
 				// 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 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
 						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;
 						}