Line 0
Link Here
|
|
|
1 |
CVE-2006-3459,3463,3464,3465 |
2 |
=================================================================== |
3 |
--- libtiff/tif_dirread.c.orig 2008-08-17 13:03:48.962994506 -0400 |
4 |
+++ libtiff/tif_dirread.c 2008-08-17 13:03:52.890034927 -0400 |
5 |
@@ -29,6 +29,9 @@ |
6 |
* |
7 |
* Directory Read Support Routines. |
8 |
*/ |
9 |
+ |
10 |
+#include <limits.h> |
11 |
+ |
12 |
#include "tiffiop.h" |
13 |
|
14 |
#define IGNORE 0 /* tag placeholder used below */ |
15 |
@@ -81,6 +84,7 @@ |
16 |
uint16 dircount; |
17 |
toff_t nextdiroff; |
18 |
int diroutoforderwarning = 0; |
19 |
+ int compressionknown = 0; |
20 |
toff_t* new_dirlist; |
21 |
|
22 |
tif->tif_diroff = tif->tif_nextdiroff; |
23 |
@@ -147,13 +151,20 @@ |
24 |
} else { |
25 |
toff_t off = tif->tif_diroff; |
26 |
|
27 |
- if (off + sizeof (uint16) > tif->tif_size) { |
28 |
- TIFFErrorExt(tif->tif_clientdata, module, |
29 |
- "%s: Can not read TIFF directory count", |
30 |
- tif->tif_name); |
31 |
- return (0); |
32 |
+ /* |
33 |
+ * Check for integer overflow when validating the dir_off, otherwise |
34 |
+ * a very high offset may cause an OOB read and crash the client. |
35 |
+ * -- taviso@google.com, 14 Jun 2006. |
36 |
+ */ |
37 |
+ if (off + sizeof (uint16) > tif->tif_size || |
38 |
+ off > (UINT_MAX - sizeof(uint16))) { |
39 |
+ TIFFErrorExt(tif->tif_clientdata, module, |
40 |
+ "%s: Can not read TIFF directory count", |
41 |
+ tif->tif_name); |
42 |
+ return (0); |
43 |
} else |
44 |
- _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16)); |
45 |
+ _TIFFmemcpy(&dircount, tif->tif_base + off, |
46 |
+ sizeof (uint16)); |
47 |
off += sizeof (uint16); |
48 |
if (tif->tif_flags & TIFF_SWAB) |
49 |
TIFFSwabShort(&dircount); |
50 |
@@ -254,6 +265,7 @@ |
51 |
while (fix < tif->tif_nfields && |
52 |
tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) |
53 |
fix++; |
54 |
+ |
55 |
if (fix >= tif->tif_nfields || |
56 |
tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { |
57 |
|
58 |
@@ -264,17 +276,23 @@ |
59 |
dp->tdir_tag, |
60 |
dp->tdir_tag, |
61 |
dp->tdir_type); |
62 |
- |
63 |
- TIFFMergeFieldInfo(tif, |
64 |
- _TIFFCreateAnonFieldInfo(tif, |
65 |
- dp->tdir_tag, |
66 |
- (TIFFDataType) dp->tdir_type), |
67 |
- 1 ); |
68 |
+ /* |
69 |
+ * creating anonymous fields prior to knowing the compression |
70 |
+ * algorithm (ie, when the field info has been merged) could cause |
71 |
+ * crashes with pathological directories. |
72 |
+ * -- taviso@google.com 15 Jun 2006 |
73 |
+ */ |
74 |
+ if (compressionknown) |
75 |
+ TIFFMergeFieldInfo(tif, _TIFFCreateAnonFieldInfo(tif, dp->tdir_tag, |
76 |
+ (TIFFDataType) dp->tdir_type), 1 ); |
77 |
+ else goto ignore; |
78 |
+ |
79 |
fix = 0; |
80 |
while (fix < tif->tif_nfields && |
81 |
tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) |
82 |
fix++; |
83 |
} |
84 |
+ |
85 |
/* |
86 |
* Null out old tags that we ignore. |
87 |
*/ |
88 |
@@ -326,6 +344,7 @@ |
89 |
dp->tdir_type, dp->tdir_offset); |
90 |
if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v)) |
91 |
goto bad; |
92 |
+ else compressionknown++; |
93 |
break; |
94 |
/* XXX: workaround for broken TIFFs */ |
95 |
} else if (dp->tdir_type == TIFF_LONG) { |
96 |
@@ -540,6 +559,7 @@ |
97 |
* Attempt to deal with a missing StripByteCounts tag. |
98 |
*/ |
99 |
if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { |
100 |
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, TIFFTAG_STRIPBYTECOUNTS); |
101 |
/* |
102 |
* Some manufacturers violate the spec by not giving |
103 |
* the size of the strips. In this case, assume there |
104 |
@@ -556,7 +576,7 @@ |
105 |
"%s: TIFF directory is missing required " |
106 |
"\"%s\" field, calculating from imagelength", |
107 |
tif->tif_name, |
108 |
- _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); |
109 |
+ fip ? fip->field_name : "Unknown"); |
110 |
if (EstimateStripByteCounts(tif, dir, dircount) < 0) |
111 |
goto bad; |
112 |
/* |
113 |
@@ -580,6 +600,7 @@ |
114 |
} else if (td->td_nstrips == 1 |
115 |
&& td->td_stripoffset[0] != 0 |
116 |
&& BYTECOUNTLOOKSBAD) { |
117 |
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, TIFFTAG_STRIPBYTECOUNTS); |
118 |
/* |
119 |
* XXX: Plexus (and others) sometimes give a value of zero for |
120 |
* a tag when they don't know what the correct value is! Try |
121 |
@@ -589,13 +610,14 @@ |
122 |
TIFFWarningExt(tif->tif_clientdata, module, |
123 |
"%s: Bogus \"%s\" field, ignoring and calculating from imagelength", |
124 |
tif->tif_name, |
125 |
- _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); |
126 |
+ fip ? fip->field_name : "Unknown"); |
127 |
if(EstimateStripByteCounts(tif, dir, dircount) < 0) |
128 |
goto bad; |
129 |
} else if (td->td_planarconfig == PLANARCONFIG_CONTIG |
130 |
&& td->td_nstrips > 2 |
131 |
&& td->td_compression == COMPRESSION_NONE |
132 |
&& td->td_stripbytecount[0] != td->td_stripbytecount[1]) { |
133 |
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, TIFFTAG_STRIPBYTECOUNTS); |
134 |
/* |
135 |
* XXX: Some vendors fill StripByteCount array with absolutely |
136 |
* wrong values (it can be equal to StripOffset array, for |
137 |
@@ -604,7 +626,7 @@ |
138 |
TIFFWarningExt(tif->tif_clientdata, module, |
139 |
"%s: Wrong \"%s\" field, ignoring and calculating from imagelength", |
140 |
tif->tif_name, |
141 |
- _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); |
142 |
+ fip ? fip->field_name : "Unknown"); |
143 |
if (EstimateStripByteCounts(tif, dir, dircount) < 0) |
144 |
goto bad; |
145 |
} |
146 |
@@ -870,7 +892,13 @@ |
147 |
|
148 |
register TIFFDirEntry *dp; |
149 |
register TIFFDirectory *td = &tif->tif_dir; |
150 |
- uint16 i; |
151 |
+ |
152 |
+ /* i is used to iterate over td->td_nstrips, so must be |
153 |
+ * at least the same width. |
154 |
+ * -- taviso@google.com 15 Jun 2006 |
155 |
+ */ |
156 |
+ |
157 |
+ uint32 i; |
158 |
|
159 |
if (td->td_stripbytecount) |
160 |
_TIFFfree(td->td_stripbytecount); |
161 |
@@ -947,16 +975,18 @@ |
162 |
static int |
163 |
CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count) |
164 |
{ |
165 |
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
166 |
+ |
167 |
if (count > dir->tdir_count) { |
168 |
TIFFWarningExt(tif->tif_clientdata, tif->tif_name, |
169 |
"incorrect count for field \"%s\" (%lu, expecting %lu); tag ignored", |
170 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, |
171 |
+ fip ? fip->field_name : "Unknown", |
172 |
dir->tdir_count, count); |
173 |
return (0); |
174 |
} else if (count < dir->tdir_count) { |
175 |
TIFFWarningExt(tif->tif_clientdata, tif->tif_name, |
176 |
"incorrect count for field \"%s\" (%lu, expecting %lu); tag trimmed", |
177 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, |
178 |
+ fip ? fip->field_name : "Unknown", |
179 |
dir->tdir_count, count); |
180 |
return (1); |
181 |
} |
182 |
@@ -970,6 +1000,7 @@ |
183 |
TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp) |
184 |
{ |
185 |
int w = TIFFDataWidth((TIFFDataType) dir->tdir_type); |
186 |
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
187 |
tsize_t cc = dir->tdir_count * w; |
188 |
|
189 |
/* Check for overflow. */ |
190 |
@@ -1013,7 +1044,7 @@ |
191 |
bad: |
192 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, |
193 |
"Error fetching data for field \"%s\"", |
194 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); |
195 |
+ fip ? fip->field_name : "Unknown"); |
196 |
return (tsize_t) 0; |
197 |
} |
198 |
|
199 |
@@ -1039,10 +1070,12 @@ |
200 |
static int |
201 |
cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv) |
202 |
{ |
203 |
+ const TIFFFieldInfo* fip; |
204 |
if (denom == 0) { |
205 |
+ fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
206 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, |
207 |
"%s: Rational with zero denominator (num = %lu)", |
208 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num); |
209 |
+ fip ? fip->field_name : "Unknown", num); |
210 |
return (0); |
211 |
} else { |
212 |
if (dir->tdir_type == TIFF_RATIONAL) |
213 |
@@ -1159,6 +1192,20 @@ |
214 |
static int |
215 |
TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir) |
216 |
{ |
217 |
+ /* |
218 |
+ * Prevent overflowing the v stack arrays below by performing a sanity |
219 |
+ * check on tdir_count, this should never be greater than two. |
220 |
+ * -- taviso@google.com 14 Jun 2006. |
221 |
+ */ |
222 |
+ if (dir->tdir_count > 2) { |
223 |
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
224 |
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name, |
225 |
+ "unexpected count for field \"%s\", %lu, expected 2; ignored.", |
226 |
+ fip ? fip->field_name : "Unknown", |
227 |
+ dir->tdir_count); |
228 |
+ return 0; |
229 |
+ } |
230 |
+ |
231 |
switch (dir->tdir_type) { |
232 |
case TIFF_BYTE: |
233 |
case TIFF_SBYTE: |
234 |
@@ -1329,14 +1376,15 @@ |
235 |
case TIFF_DOUBLE: |
236 |
return (TIFFFetchDoubleArray(tif, dir, (double*) v)); |
237 |
default: |
238 |
+ { const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
239 |
/* TIFF_NOTYPE */ |
240 |
/* TIFF_ASCII */ |
241 |
/* TIFF_UNDEFINED */ |
242 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, |
243 |
"cannot read TIFF_ANY type %d for field \"%s\"", |
244 |
dir->tdir_type, |
245 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); |
246 |
- return (0); |
247 |
+ fip ? fip->field_name : "Unknown"); |
248 |
+ return (0); } |
249 |
} |
250 |
return (1); |
251 |
} |
252 |
@@ -1351,6 +1399,9 @@ |
253 |
int ok = 0; |
254 |
const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag); |
255 |
|
256 |
+ if (fip == NULL) { |
257 |
+ return (0); |
258 |
+ } |
259 |
if (dp->tdir_count > 1) { /* array of values */ |
260 |
char* cp = NULL; |
261 |
|
262 |
@@ -1493,6 +1544,7 @@ |
263 |
TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, uint16* pl) |
264 |
{ |
265 |
uint16 samples = tif->tif_dir.td_samplesperpixel; |
266 |
+ const TIFFFieldInfo* fip; |
267 |
int status = 0; |
268 |
|
269 |
if (CheckDirCount(tif, dir, (uint32) samples)) { |
270 |
@@ -1510,9 +1562,10 @@ |
271 |
|
272 |
for (i = 1; i < check_count; i++) |
273 |
if (v[i] != v[0]) { |
274 |
+ fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
275 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, |
276 |
"Cannot handle different per-sample values for field \"%s\"", |
277 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); |
278 |
+ fip ? fip->field_name : "Unknown"); |
279 |
goto bad; |
280 |
} |
281 |
*pl = v[0]; |
282 |
@@ -1534,6 +1587,7 @@ |
283 |
TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntry* dir, uint32* pl) |
284 |
{ |
285 |
uint16 samples = tif->tif_dir.td_samplesperpixel; |
286 |
+ const TIFFFieldInfo* fip; |
287 |
int status = 0; |
288 |
|
289 |
if (CheckDirCount(tif, dir, (uint32) samples)) { |
290 |
@@ -1551,9 +1605,10 @@ |
291 |
check_count = samples; |
292 |
for (i = 1; i < check_count; i++) |
293 |
if (v[i] != v[0]) { |
294 |
+ fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
295 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, |
296 |
"Cannot handle different per-sample values for field \"%s\"", |
297 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); |
298 |
+ fip ? fip->field_name : "Unknown"); |
299 |
goto bad; |
300 |
} |
301 |
*pl = v[0]; |
302 |
@@ -1574,6 +1629,7 @@ |
303 |
TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl) |
304 |
{ |
305 |
uint16 samples = tif->tif_dir.td_samplesperpixel; |
306 |
+ const TIFFFieldInfo* fip; |
307 |
int status = 0; |
308 |
|
309 |
if (CheckDirCount(tif, dir, (uint32) samples)) { |
310 |
@@ -1591,9 +1647,10 @@ |
311 |
|
312 |
for (i = 1; i < check_count; i++) |
313 |
if (v[i] != v[0]) { |
314 |
+ fip = _TIFFFieldWithTag(tif, dir->tdir_tag); |
315 |
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, |
316 |
"Cannot handle different per-sample values for field \"%s\"", |
317 |
- _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); |
318 |
+ fip ? fip->field_name : "Unknown"); |
319 |
goto bad; |
320 |
} |
321 |
*pl = v[0]; |
322 |
Index: tiff-3.8.2/libtiff/tif_fax3.c |